Project

General

Profile

Download (134 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 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.cdmLight;
10

    
11
import java.io.File;
12
import java.util.ArrayList;
13
import java.util.Collection;
14
import java.util.Collections;
15
import java.util.Comparator;
16
import java.util.HashSet;
17
import java.util.Iterator;
18
import java.util.List;
19
import java.util.Map;
20
import java.util.Set;
21
import java.util.UUID;
22

    
23
import org.apache.commons.lang3.StringUtils;
24
import org.springframework.beans.factory.annotation.Autowired;
25
import org.springframework.stereotype.Component;
26

    
27
import eu.etaxonomy.cdm.api.service.dto.CondensedDistribution;
28
import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetFormatter;
29
import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetManager;
30
import eu.etaxonomy.cdm.common.CdmUtils;
31
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
32
import eu.etaxonomy.cdm.compare.name.TypeComparator;
33
import eu.etaxonomy.cdm.compare.taxon.HomotypicGroupTaxonComparator;
34
import eu.etaxonomy.cdm.ext.geo.IEditGeoService;
35
import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
36
import eu.etaxonomy.cdm.format.reference.OriginalSourceFormatter;
37
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
38
import eu.etaxonomy.cdm.io.common.CdmExportBase;
39
import eu.etaxonomy.cdm.io.common.ExportResult.ExportResultState;
40
import eu.etaxonomy.cdm.io.common.TaxonNodeOutStreamPartitioner;
41
import eu.etaxonomy.cdm.io.common.XmlExportState;
42
import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
43
import eu.etaxonomy.cdm.model.agent.AgentBase;
44
import eu.etaxonomy.cdm.model.agent.Person;
45
import eu.etaxonomy.cdm.model.agent.Team;
46
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
47
import eu.etaxonomy.cdm.model.common.Annotation;
48
import eu.etaxonomy.cdm.model.common.AnnotationType;
49
import eu.etaxonomy.cdm.model.common.CdmBase;
50
import eu.etaxonomy.cdm.model.common.ICdmBase;
51
import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
52
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
53
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
54
import eu.etaxonomy.cdm.model.common.Identifier;
55
import eu.etaxonomy.cdm.model.common.Language;
56
import eu.etaxonomy.cdm.model.common.LanguageString;
57
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
58
import eu.etaxonomy.cdm.model.description.DescriptionBase;
59
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
60
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
61
import eu.etaxonomy.cdm.model.description.Distribution;
62
import eu.etaxonomy.cdm.model.description.Feature;
63
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
64
import eu.etaxonomy.cdm.model.description.TaxonDescription;
65
import eu.etaxonomy.cdm.model.description.TaxonInteraction;
66
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
67
import eu.etaxonomy.cdm.model.description.TextData;
68
import eu.etaxonomy.cdm.model.location.NamedArea;
69
import eu.etaxonomy.cdm.model.media.ExternalLink;
70
import eu.etaxonomy.cdm.model.media.Media;
71
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
72
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
73
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
74
import eu.etaxonomy.cdm.model.name.NameRelationship;
75
import eu.etaxonomy.cdm.model.name.NameRelationshipType;
76
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
77
import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
78
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
79
import eu.etaxonomy.cdm.model.name.Rank;
80
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
81
import eu.etaxonomy.cdm.model.name.TaxonName;
82
import eu.etaxonomy.cdm.model.name.TextualTypeDesignation;
83
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
84
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
85
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
86
import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
87
import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
88
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
89
import eu.etaxonomy.cdm.model.reference.NamedSource;
90
import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
91
import eu.etaxonomy.cdm.model.reference.Reference;
92
import eu.etaxonomy.cdm.model.reference.ReferenceType;
93
import eu.etaxonomy.cdm.model.taxon.Classification;
94
import eu.etaxonomy.cdm.model.taxon.Synonym;
95
import eu.etaxonomy.cdm.model.taxon.Taxon;
96
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
97
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
98
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
99
import eu.etaxonomy.cdm.model.term.DefinedTerm;
100
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
101
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDtoByRankAndNameComparator;
102
import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
103
import eu.etaxonomy.cdm.strategy.cache.TagEnum;
104
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
105
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
106

    
107
/**
108
 * @author k.luther
109
 * @since 15.03.2017
110
 */
111
@Component
112
public class CdmLightClassificationExport
113
        extends CdmExportBase<CdmLightExportConfigurator, CdmLightExportState, IExportTransformer, File>{
114

    
115
    private static final long serialVersionUID = 2518643632756927053L;
116

    
117
    private static final String IPNI_NAME_IDENTIFIER = "Ipni Name Identifier";
118
    private static final String TROPICOS_NAME_IDENTIFIER = "Tropicos Name Identifier";
119
    private static final String WFO_NAME_IDENTIFIER = "WFO Name Identifier";
120

    
121
    @Autowired
122
    IEditGeoService geoService;
123

    
124
    public CdmLightClassificationExport() {
125
        super();
126
        this.ioName = this.getClass().getSimpleName();
127
    }
128

    
129
    @Override
130
    public long countSteps(CdmLightExportState state) {
131
        TaxonNodeFilter filter = state.getConfig().getTaxonNodeFilter();
132
        return getTaxonNodeService().count(filter);
133
    }
134

    
135
    @Override
136
    protected void doInvoke(CdmLightExportState state) {
137
        try {
138

    
139
            IProgressMonitor monitor = state.getConfig().getProgressMonitor();
140
            CdmLightExportConfigurator config = state.getConfig();
141
            if (config.getTaxonNodeFilter().hasClassificationFilter()) {
142
                Classification classification = getClassificationService()
143
                        .load(config.getTaxonNodeFilter().getClassificationFilter().get(0).getUuid());
144
                state.setRootId(classification.getRootNode().getUuid());
145

    
146
            } else if (config.getTaxonNodeFilter().hasSubtreeFilter()) {
147
                state.setRootId(config.getTaxonNodeFilter().getSubtreeFilter().get(0).getUuid());
148
            }
149
            @SuppressWarnings("unchecked")
150
            TaxonNodeOutStreamPartitioner<XmlExportState> partitioner = TaxonNodeOutStreamPartitioner.NewInstance(this,
151
                    state, state.getConfig().getTaxonNodeFilter(), 100, monitor, null);
152

    
153
            handleMetaData(state);
154
            monitor.subTask("Start partitioning");
155

    
156
            TaxonNode node = partitioner.next();
157
            while (node != null) {
158
                handleTaxonNode(state, node);
159
                node = partitioner.next();
160
            }
161
            // get rootNode and create helperObjects
162
            if (state.getRootId() != null) {
163
                List<TaxonNodeDto> childrenOfRoot = state.getNodeChildrenMap().get(state.getRootId());
164

    
165
                Comparator<TaxonNodeDto> comp = state.getConfig().getComparator();
166
                if (comp == null) {
167
                    comp = new TaxonNodeDtoByRankAndNameComparator();
168
                }
169
                if (childrenOfRoot != null) {
170
                    Collections.sort(childrenOfRoot, comp);
171
                    OrderHelper helper = new OrderHelper(state.getRootId());
172
                    helper.setOrderIndex(state.getActualOrderIndexAndUpdate());
173
                    state.getOrderHelperMap().put(state.getRootId(), helper);
174

    
175
                    for (TaxonNodeDto child : childrenOfRoot) {
176
                        OrderHelper childHelper = new OrderHelper(child.getTaxonUuid());
177
                        helper.addChild(childHelper);
178
                        childHelper.setOrderIndex(state.getActualOrderIndexAndUpdate());
179
                        childHelper.addChildren(
180
                                createOrderHelper(state.getNodeChildrenMap().get(child.getUuid()), state));
181
                    }
182
                }
183

    
184
                state.getNodeChildrenMap().clear();
185
                for (OrderHelper order : state.getOrderHelperMap().values()) {
186
                    setOrderIndex(state, order);
187
                }
188
            }
189

    
190
            state.getProcessor().createFinalResult(state);
191
        } catch (Exception e) {
192
            state.getResult().addException(e,
193
                    "An unexpected error occurred in main method doInvoke() " + e.getMessage());
194
            e.printStackTrace();
195
        }
196
    }
197

    
198
    private void setOrderIndex(CdmLightExportState state, OrderHelper order) {
199

    
200
        // String sortIndex = StringUtils.isBlank(sort_index)?
201
        // String.valueOf(order.getOrderIndex()): sort_index+ "_"
202
        // +String.valueOf(order.getOrderIndex());
203

    
204
        if (order.getTaxonUuid() != null
205
                && state.getProcessor().hasRecord(CdmLightExportTable.TAXON, order.getTaxonUuid().toString())) {
206
            String[] csvLine = state.getProcessor().getRecord(CdmLightExportTable.TAXON,
207
                    order.getTaxonUuid().toString());
208
            csvLine[CdmLightExportTable.TAXON.getIndex(CdmLightExportTable.SORT_INDEX)] = String
209
                    .valueOf(order.getOrderIndex());
210
        }
211

    
212
        if (order.getChildren() == null) {
213
            return;
214
        }
215
        for (OrderHelper helper : order.getChildren()) {
216
            setOrderIndex(state, helper);
217
        }
218
    }
219

    
220
    private List<OrderHelper> createOrderHelper(List<TaxonNodeDto> nodes, CdmLightExportState state) {
221
        List<TaxonNodeDto> children = nodes;
222
        // alreadySortedNodes.add(parentUuid);
223
        if (children == null) {
224
            return null;
225
        }
226
        Comparator<TaxonNodeDto> comp = state.getConfig().getComparator();
227
        if (comp == null) {
228
            comp = new TaxonNodeDtoByRankAndNameComparator();
229
        }
230
        Collections.sort(children, comp);
231
        // TODO: nochmal checken!!!
232
        OrderHelper helperChild;
233
        List<OrderHelper> childrenHelper = new ArrayList<>();
234
        for (TaxonNodeDto child : children) {
235
            helperChild = new OrderHelper(child.getTaxonUuid());
236
            helperChild.setOrderIndex(state.getActualOrderIndexAndUpdate());
237

    
238
            if (state.getNodeChildrenMap().get(child.getUuid()) != null) {
239
                children = state.getNodeChildrenMap().get(child.getUuid());
240
                helperChild.addChildren(createOrderHelper(children, state));
241
            }
242
            childrenHelper.add(helperChild);
243
        }
244
        return childrenHelper;
245
    }
246

    
247
    private void handleTaxonNode(CdmLightExportState state, TaxonNode taxonNode) {
248

    
249
        if (taxonNode == null) {
250
            String message = "TaxonNode for given taxon node UUID not found. ";
251
            // TODO
252
            state.getResult().addWarning(message);
253
        } else {
254
            try {
255
                TaxonNode root = taxonNode;
256
                List<TaxonNodeDto> childNodes;
257
                if (root.hasChildNodes()) {
258
                    childNodes = new ArrayList<>();
259
                    for (TaxonNode child : root.getChildNodes()) {
260
                    	if (child != null) {
261
                    		childNodes.add(new TaxonNodeDto(child));
262
                    	}
263
                    }
264
                    state.getNodeChildrenMap().put(root.getUuid(), childNodes);
265

    
266
                    // add root to node map
267

    
268
                }
269
                TaxonNodeDto rootDto = new TaxonNodeDto(root);
270
                UUID parentUuid = root.getParent() != null ? root.getParent().getUuid()
271
                        : state.getClassificationUUID(root);
272
                List<TaxonNodeDto> children = state.getNodeChildrenMap().get(parentUuid);
273
                if (children != null && !children.contains(rootDto)) {
274
                    state.getNodeChildrenMap().get(parentUuid).add(rootDto);
275
                } else if (state.getNodeChildrenMap().get(parentUuid) == null) {
276
                    List<TaxonNodeDto> rootList = new ArrayList<>();
277
                    rootList.add(rootDto);
278
                    state.getNodeChildrenMap().put(parentUuid, rootList);
279

    
280
                }
281
                if (root.hasTaxon()) {
282
                    handleTaxon(state, root);
283

    
284
                }
285
            } catch (Exception e) {
286
                state.getResult().addException(e, "An unexpected error occurred when handling taxonNode "
287
                        + taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
288
            }
289
        }
290
    }
291

    
292
    private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
293
        try {
294

    
295
            if (taxonNode == null) {
296
                state.getResult().addError("The taxonNode was null.", "handleTaxon");
297
                state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
298
                return;
299
            }
300
            if (taxonNode.getTaxon() == null) {
301
                state.getResult().addError("There was a taxon node without a taxon: " + taxonNode.getUuid(),
302
                        "handleTaxon");
303
                state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
304
            } else {
305
                Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon());
306

    
307
                try {
308
                    TaxonName name = taxon.getName();
309
                    handleName(state, name, taxon, true);
310
                    HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
311
                    int index = 0;
312
                    int homotypicGroupIndex = 0;
313
                    handleHomotypicalGroup(state, homotypicGroup, taxon, homotypicGroupIndex);
314
                    homotypicGroupIndex++;
315
                    for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
316
                        handleSynonym(state, syn, index);
317
                        index++;
318
                    }
319
                    List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
320
                    for (HomotypicalGroup group: heterotypicHomotypicGroups){
321
                        handleHomotypicalGroup(state, group, taxon, homotypicGroupIndex);
322
                        for (Synonym syn : taxon.getSynonymsInGroup(group)) {
323
                            handleSynonym(state, syn, index);
324
                            index++;
325
                        }
326
                        homotypicGroupIndex++;
327
                    }
328

    
329
                    index = 0;
330
                    for (Taxon tax : taxon.getAllProParteSynonyms()) {
331
                        handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
332
                        index++;
333
                    }
334

    
335

    
336
                    for (Taxon tax : taxon.getAllMisappliedNames()) {
337
                        handleProPartePartialMisapplied(state, tax, taxon, false, true, index);
338
                        index++;
339
                    }
340

    
341
                    CdmLightExportTable table = CdmLightExportTable.TAXON;
342
                    String[] csvLine = new String[table.getSize()];
343

    
344
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_ID)] = getId(state, taxon);
345
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
346
                    Taxon parent = (taxonNode.getParent() == null) ? null : taxonNode.getParent().getTaxon();
347
                    csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
348
                    csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
349
                    if (taxon.getSec() != null && taxon.getSec().getDatePublished() != null
350
                            && taxon.getSec().getDatePublished().getFreeText() != null) {
351
                        String sec_string = taxon.getSec().getTitleCache() + ". "
352
                                + taxon.getSec().getDatePublished().getFreeText();
353
                        sec_string = sec_string.replace("..", ".");
354
                        csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = sec_string;
355
                    } else {
356
                        csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(taxon.getSec());
357
                    }
358
                    if (taxon.getSec() != null) {
359
                        if (!state.getReferenceStore().contains((taxon.getSec().getUuid()))) {
360
                            handleReference(state, taxon.getSec());
361
                        }
362
                    }
363
                    csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = taxon.getAppendedPhrase();
364
                    csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state,
365
                            taxonNode.getClassification());
366
                    csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification()
367
                            .getTitleCache();
368

    
369
                    csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = taxon.isPublish() ? "1" : "0";
370
                    csvLine[table.getIndex(CdmLightExportTable.EXCLUDED)] = taxonNode.isExcluded() ? "1" : "0";
371
                    Map<Language, LanguageString> notesMap = taxonNode.getStatusNote();
372
                    String statusNotes = "";
373
                    if (!notesMap.isEmpty() && notesMap.size() == 1) {
374
                        statusNotes = notesMap.values().iterator().next().getText();
375
                    } else if (!notesMap.isEmpty()) {
376
                        statusNotes = notesMap.get(Language.getDefaultLanguage()) != null
377
                                ? notesMap.get(Language.getDefaultLanguage()).getText() : null;
378
                        if (statusNotes == null) {
379
                            statusNotes = notesMap.values().iterator().next().getText();
380
                        }
381
                    }
382
                    csvLine[table.getIndex(CdmLightExportTable.STATUS_NOTES)] = statusNotes;
383

    
384
                    csvLine[table.getIndex(CdmLightExportTable.UNPLACED)] = taxonNode.isUnplaced() ? "1" : "0";
385
                    csvLine[table.getIndex(CdmLightExportTable.DOUBTFUL)] = taxonNode.isDoubtful() ? "1" : "0";
386
                    state.getProcessor().put(table, taxon, csvLine);
387
                    handleDescriptions(state, taxon);
388
                } catch (Exception e) {
389
                    state.getResult().addException(e,
390
                            "An unexpected problem occurred when trying to export taxon with id " + taxon.getId() + " " + taxon.getTitleCache());
391
                    state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
392
                }
393
            }
394

    
395
            taxonNode.removeNullValueFromChildren();
396

    
397
        } catch (Exception e) {
398
            state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
399
                    + cdmBaseStr(taxonNode.getTaxon()) + ", titleCache:"+ taxonNode.getTaxon().getTitleCache()+": " + e.getMessage());
400
        }
401
    }
402

    
403
    private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
404
        String titleCache = null;
405
        try {
406

    
407
            if (cdmBase instanceof Taxon) {
408
                Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
409
                titleCache = taxon.getTitleCache();
410
                Set<TaxonDescription> descriptions = taxon.getDescriptions();
411
                List<DescriptionElementBase> simpleFacts = new ArrayList<>();
412
                List<DescriptionElementBase> specimenFacts = new ArrayList<>();
413
                List<DescriptionElementBase> distributionFacts = new ArrayList<>();
414
                List<DescriptionElementBase> taxonInteractionsFacts = new ArrayList<>();
415
                List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
416
                List<DescriptionElementBase> usageFacts = new ArrayList<>();
417
                for (TaxonDescription description : descriptions) {
418
                    if (description.getElements() != null) {
419
                        for (DescriptionElementBase element : description.getElements()) {
420
                            element = CdmBase.deproxy(element);
421
                            handleAnnotations(element);
422
                            if (element.getFeature().equals(Feature.COMMON_NAME())) {
423
                                commonNameFacts.add(element);
424
                            } else if (element.getFeature().equals(Feature.DISTRIBUTION())) {
425
                                distributionFacts.add(element);
426
                            } else if (element instanceof IndividualsAssociation
427
                                    || isSpecimenFeature(element.getFeature())) {
428
                                specimenFacts.add(element);
429
                            } else if (element.getFeature().isSupportsTaxonInteraction()) {
430
                                taxonInteractionsFacts.add(element);
431
                            } else {
432
                                simpleFacts.add(element);
433
                            }
434
                        }
435
                    }
436
                }
437
                if (!commonNameFacts.isEmpty()) {
438
                    handleCommonNameFacts(state, taxon, commonNameFacts);
439
                }
440
                if (!distributionFacts.isEmpty()) {
441
                    handleDistributionFacts(state, taxon, distributionFacts);
442
                }
443
                if (!specimenFacts.isEmpty()) {
444
                    handleSpecimenFacts(state, taxon, specimenFacts);
445
                }
446
                if (!simpleFacts.isEmpty()) {
447
                    handleSimpleFacts(state, taxon, simpleFacts);
448
                }
449
                if (!taxonInteractionsFacts.isEmpty()) {
450
                    handleTaxonInteractionsFacts(state, taxon, taxonInteractionsFacts);
451
                }
452
            } else if (cdmBase instanceof TaxonName) {
453
                TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
454
                titleCache = name.getTitleCache();
455
                Set<TaxonNameDescription> descriptions = name.getDescriptions();
456
                List<DescriptionElementBase> simpleFacts = new ArrayList<>();
457
                for (TaxonNameDescription description : descriptions) {
458
                    if (description.getElements() != null) {
459
                        for (DescriptionElementBase element : description.getElements()) {
460
                            simpleFacts.add(element);
461
                        }
462
                    }
463
                }
464
                if (!simpleFacts.isEmpty()) {
465
                    handleSimpleFacts(state, name, simpleFacts);
466
                }
467
            }
468
        } catch (Exception e) {
469
            state.getResult().addException(e, "An unexpected error occurred when handling description of "
470
                    + cdmBaseStr(cdmBase) + (titleCache != null? (" " +titleCache) : "")+": " + e.getMessage());
471
        }
472
    }
473

    
474
    private void handleAnnotations(DescriptionElementBase element) {
475
        // TODO Auto-generated method stub
476
    }
477

    
478
    private void handleMetaData(CdmLightExportState state) {
479
        CdmLightExportTable table = CdmLightExportTable.METADATA;
480
        String[] csvLine = new String[table.getSize()];
481
//        csvLine[table.getIndex(CdmLightExportTable.INSTANCE_ID)] = state.getConfig().getInctanceId();
482
//        csvLine[table.getIndex(CdmLightExportTable.INSTANCE_NAME)] = state.getConfig().getInstanceName();
483
        csvLine[table.getIndex(CdmLightExportTable.DATASET_BASE_URL)] = state.getConfig().getBase_url();
484
        csvLine[table.getIndex(CdmLightExportTable.DATASET_CONTRIBUTOR)] = state.getConfig().getContributor();
485
        csvLine[table.getIndex(CdmLightExportTable.DATASET_CREATOR)] = state.getConfig().getCreator();
486
        csvLine[table.getIndex(CdmLightExportTable.DATASET_DESCRIPTION)] = state.getConfig().getDescription();
487
        csvLine[table.getIndex(CdmLightExportTable.DATASET_DOWNLOAD_LINK)] = state.getConfig().getDataset_download_link();
488
        csvLine[table.getIndex(CdmLightExportTable.DATASET_KEYWORDS)] = state.getConfig().getKeywords();
489
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANDINGPAGE)] = state.getConfig().getDataSet_landing_page();
490

    
491
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
492
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
493
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
494
        csvLine[table.getIndex(CdmLightExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
495
        csvLine[table.getIndex(CdmLightExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
496
        state.getProcessor().put(table, "", csvLine);
497
    }
498

    
499
    private boolean isSpecimenFeature(Feature feature) {
500
        // TODO allow user defined specimen features
501
        if (feature == null) {
502
            return false;
503
        } else if (feature.isSupportsIndividualAssociation()) {
504
            return true;
505
        } else {
506
            return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
507
                    || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
508
                    || feature.equals(Feature.OCCURRENCE());
509
        }
510
    }
511

    
512
    private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
513
            List<DescriptionElementBase> simpleFacts) {
514
        String titleCache = null;
515
        try {
516
            CdmLightExportTable table;
517
            if (cdmBase instanceof TaxonName) {
518
                titleCache = ((TaxonName)cdmBase).getTitleCache();
519
                table = CdmLightExportTable.NAME_FACT;
520
            } else {
521
                if (cdmBase instanceof Taxon){
522
                    titleCache = ((Taxon)cdmBase).getTitleCache();
523
                }
524
                table = CdmLightExportTable.SIMPLE_FACT;
525
            }
526
            CdmLightExportTable tableMedia = CdmLightExportTable.MEDIA;
527
            for (DescriptionElementBase element : simpleFacts) {
528
                if (element.getModifyingText().isEmpty() && !element.getMedia().isEmpty()) {
529
                    handleSimpleMediaFact(state, cdmBase, tableMedia, element);
530
                } else {
531
                    handleSingleSimpleFact(state, cdmBase, table, element);
532
                }
533
            }
534
        } catch (Exception e) {
535
            state.getResult().addException(e, "An unexpected error occurred when handling simple facts for "
536
                    + cdmBaseStr(cdmBase) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
537
        }
538
    }
539

    
540
    private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
541
            List<DescriptionElementBase> taxonInteractionsFacts) {
542
        CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
543
        String titleCache = null;
544
        if (cdmBase instanceof TaxonBase){
545
            titleCache = ((TaxonBase)cdmBase).getTitleCache();
546
        }
547
        for (DescriptionElementBase element : taxonInteractionsFacts) {
548

    
549
            try {
550

    
551
                String[] csvLine = new String[table.getSize()];
552

    
553
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
554
                handleSource(state, element, table);
555
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
556
                csvLine[table.getIndex(CdmLightExportTable.TAXON2_FK)] = getId(state,
557
                        ((TaxonInteraction) element).getTaxon2());
558
                csvLine[table.getIndex(CdmLightExportTable.DESCRIPTION)] = createMultilanguageString(
559
                        ((TaxonInteraction) element).getDescription());
560
                state.getProcessor().put(table, element, csvLine);
561

    
562
            } catch (Exception e) {
563
                state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
564
                        + cdmBaseStr(element) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
565
            }
566
        }
567
    }
568

    
569
    private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
570
            DescriptionElementBase element) {
571
        try {
572
            String[] csvLine;
573
            handleSource(state, element, CdmLightExportTable.MEDIA);
574

    
575
            if (element instanceof TextData) {
576
                TextData textData = (TextData) element;
577
                csvLine = new String[table.getSize()];
578
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
579
                if (cdmBase instanceof Taxon) {
580
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
581
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
582
                } else if (cdmBase instanceof TaxonName) {
583
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
584
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
585
                }
586

    
587
                String mediaUris = "";
588
                for (Media media : textData.getMedia()) {
589
                    String mediaString = extractMediaUris(media.getRepresentations().iterator());
590
                    if (!StringUtils.isBlank(mediaString)) {
591
                        mediaUris += mediaString + ";";
592
                    } else {
593
                        state.getResult().addWarning("Empty Media object for " + cdmBase.getUserFriendlyTypeName() + " "
594
                                + cdmBase.getUuid() + " (media: " + media.getUuid() + ")");
595
                    }
596
                }
597
                csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
598

    
599
            }
600
        } catch (Exception e) {
601
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
602
                    + cdmBaseStr(element) + ": " + e.getMessage());
603
        }
604

    
605
    }
606

    
607
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
608
            DescriptionElementBase element) {
609
        try {
610
            String[] csvLine;
611
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
612

    
613
            if (element instanceof TextData) {
614
                TextData textData = (TextData) element;
615
                csvLine = new String[table.getSize()];
616
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
617
                if (cdmBase instanceof Taxon) {
618
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
619
                } else if (cdmBase instanceof TaxonName) {
620
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
621
                }
622
                csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
623

    
624
                String mediaUris = "";
625
                for (Media media : textData.getMedia()) {
626
                    String mediaString = extractMediaUris(media.getRepresentations().iterator());
627
                    if (!StringUtils.isBlank(mediaString)) {
628
                        mediaUris += mediaString + ";";
629
                    } else {
630
                        state.getResult().addWarning("Empty Media object for uuid: " + cdmBase.getUuid()
631
                                + " uuid of media: " + media.getUuid());
632
                    }
633
                }
634
                csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
635
                if (textData.getFeature().equals(Feature.CITATION())) {
636
                    state.getProcessor().put(table, textData, csvLine);
637
                } else if (!textData.getMultilanguageText().isEmpty()) {
638
                    for (Language language : textData.getMultilanguageText().keySet()) {
639
                        String[] csvLineLanguage = csvLine.clone();
640
                        LanguageString langString = textData.getLanguageText(language);
641
                        String text = langString.getText();
642
                        if (state.getConfig().isFilterIntextReferences()) {
643
                            text = filterIntextReferences(langString.getText());
644
                        }
645
                        csvLineLanguage[table.getIndex(CdmLightExportTable.FACT_TEXT)] = text;
646
                        csvLineLanguage[table.getIndex(CdmLightExportTable.LANGUAGE)] = language.getLabel();
647
                        state.getProcessor().put(table, textData, csvLineLanguage);
648
                    }
649
                } else {
650
                    state.getProcessor().put(table, textData, csvLine);
651
                }
652
            }
653
        } catch (Exception e) {
654
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
655
                    + cdmBaseStr(element) + ": " + e.getMessage());
656
        }
657
    }
658

    
659
    private String filterIntextReferences(String text) {
660
        /*
661
         * (<cdm:reference cdmId='fbd19251-efee-4ded-b780-915000f66d41'
662
         * intextId='1352d42c-e201-4155-a02a-55360d3b563e'>Ridley in Fl. Malay
663
         * Pen. 3 (1924) 22</cdm:reference>)
664
         */
665
        String newText = text.replaceAll("<cdm:reference cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
666
        newText = newText.replaceAll("</cdm:reference>", "");
667

    
668
        newText = newText.replaceAll("<cdm:key cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
669
        newText = newText.replaceAll("</cdm:key>", "");
670
        return newText;
671
    }
672

    
673
    private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon,
674
            List<DescriptionElementBase> specimenFacts) {
675
        CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
676

    
677
        for (DescriptionElementBase element : specimenFacts) {
678
            try {
679
                String[] csvLine = new String[table.getSize()];
680
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
681
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
682
                handleSource(state, element, table);
683
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(
684
                        element.getAnnotations());
685

    
686
                if (element instanceof IndividualsAssociation) {
687

    
688
                    IndividualsAssociation indAssociation = (IndividualsAssociation) element;
689
                    if (indAssociation.getAssociatedSpecimenOrObservation() == null) {
690
                        state.getResult()
691
                                .addWarning("There is an individual association with no specimen associated (Taxon "
692
                                        + taxon.getTitleCache() + "(" + taxon.getUuid() + "). Could not be exported.");
693
                        continue;
694
                    } else {
695
                        if (!state.getSpecimenStore()
696
                                .contains((indAssociation.getAssociatedSpecimenOrObservation().getUuid()))) {
697
                            SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(
698
                                    indAssociation.getAssociatedSpecimenOrObservation(),
699
                                    SpecimenOrObservationBase.class);
700

    
701
                            handleSpecimen(state, specimenBase);
702
                            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
703
                                    indAssociation.getAssociatedSpecimenOrObservation());
704
                        }
705
                    }
706
                } else if (element instanceof TextData) {
707
                    TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
708
                    csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(
709
                            textData.getMultilanguageText());
710
                }
711
                state.getProcessor().put(table, element, csvLine);
712
            } catch (Exception e) {
713
                state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact "
714
                        + cdmBaseStr(element) + ": " + e.getMessage());
715
            }
716
        }
717
    }
718

    
719
    private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
720
        String text = "";
721
        int index = multilanguageText.size();
722
        for (LanguageString langString : multilanguageText.values()) {
723
            text += langString.getText();
724
            if (index > 1) {
725
                text += "; ";
726
            }
727
            index--;
728
        }
729
        return text;
730
    }
731

    
732
    private String createAnnotationsString(Set<Annotation> annotations) {
733
        StringBuffer strBuff = new StringBuffer();
734

    
735
        for (Annotation ann : annotations) {
736
            if (ann.getAnnotationType() == null || !ann.getAnnotationType().equals(AnnotationType.TECHNICAL())) {
737
                strBuff.append(ann.getText());
738
                strBuff.append("; ");
739
            }
740
        }
741

    
742
        if (strBuff.length() > 2) {
743
            return strBuff.substring(0, strBuff.length() - 2);
744
        } else {
745
            return null;
746
        }
747
    }
748

    
749
    private void handleSource(CdmLightExportState state, DescriptionElementBase element,
750
            CdmLightExportTable factsTable) {
751
        CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
752
        try {
753
            Set<DescriptionElementSource> sources = element.getSources();
754

    
755
            for (DescriptionElementSource source : sources) {
756
                if (!(source.getType().equals(OriginalSourceType.Import)
757
                        && state.getConfig().isFilterImportSources())) {
758
                    String[] csvLine = new String[table.getSize()];
759
                    Reference ref = source.getCitation();
760
                    if ((ref == null) && (source.getNameUsedInSource() == null)) {
761
                        continue;
762
                    }
763
                    if (ref != null) {
764
                        if (!state.getReferenceStore().contains(ref.getUuid())) {
765
                            handleReference(state, ref);
766

    
767
                        }
768
                        csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
769
                    }
770
                    csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
771

    
772
                    csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state,
773
                            source.getNameUsedInSource());
774
                    csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
775
                    if (StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])
776
                            && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])) {
777
                        continue;
778
                    }
779
                    state.getProcessor().put(table, source, csvLine);
780
                }
781

    
782
            }
783
        } catch (Exception e) {
784
            state.getResult().addException(e, "An unexpected error occurred when handling single source "
785
                    + cdmBaseStr(element) + ": " + e.getMessage());
786
        }
787

    
788
    }
789

    
790
    private void handleDistributionFacts(CdmLightExportState state, Taxon taxon,
791
            List<DescriptionElementBase> distributionFacts) {
792

    
793
        CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
794
        Set<Distribution> distributions = new HashSet<>();
795
        for (DescriptionElementBase element : distributionFacts) {
796
            try {
797
                if (element instanceof Distribution) {
798
                    String[] csvLine = new String[table.getSize()];
799
                    Distribution distribution = (Distribution) element;
800
                    distributions.add(distribution);
801
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
802
                    handleSource(state, element, table);
803
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
804
                    if (distribution.getArea() != null) {
805
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = distribution.getArea().getLabel();
806
                    }
807
                    if (distribution.getStatus() != null) {
808
                        csvLine[table.getIndex(CdmLightExportTable.STATUS_LABEL)] = distribution.getStatus().getLabel();
809
                    }
810
                    state.getProcessor().put(table, distribution, csvLine);
811
                } else {
812
                    state.getResult()
813
                            .addError("The distribution description for the taxon " + taxon.getUuid()
814
                                    + " is not of type distribution. Could not be exported. UUID of the description element: "
815
                                    + element.getUuid());
816
                }
817
            } catch (Exception e) {
818
                state.getResult().addException(e, "An unexpected error occurred when handling single distribution "
819
                        + cdmBaseStr(element) + ": " + e.getMessage());
820
            }
821
        }
822
         if(state.getConfig().isCreateCondensedDistributionString()){
823
             List<Language> langs = new ArrayList<>();
824
             langs.add(Language.ENGLISH());
825

    
826
             CondensedDistribution conDis = geoService.getCondensedDistribution(
827
                     //TODO add CondensedDistributionConfiguration to export configuration
828
                     distributions, true, null, state.getConfig().getCondensedDistributionConfiguration(), langs);
829
             CdmLightExportTable tableCondensed =
830
                     CdmLightExportTable.SIMPLE_FACT;
831
             String[] csvLine = new String[tableCondensed.getSize()];
832
             //the computed fact has no uuid, TODO: remember the uuid for later reference assignment
833
             UUID randomUuid = UUID.randomUUID();
834
             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_ID)] =
835
                     randomUuid.toString();
836
             csvLine[tableCondensed.getIndex(CdmLightExportTable.TAXON_FK)] =
837
                     getId(state, taxon);
838
             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
839
                     conDis.toString();
840
             csvLine[tableCondensed.getIndex(CdmLightExportTable.LANGUAGE)] =Language.ENGLISH().toString();
841

    
842
             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_CATEGORY)] =
843
                     "CondensedDistribution";
844

    
845
             state.getProcessor().put(tableCondensed, taxon, csvLine);
846
         }
847
    }
848

    
849
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
850
            List<DescriptionElementBase> commonNameFacts) {
851
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
852

    
853
        for (DescriptionElementBase element : commonNameFacts) {
854
            try {
855
                if (element instanceof CommonTaxonName) {
856
                    String[] csvLine = new String[table.getSize()];
857
                    CommonTaxonName commonName = (CommonTaxonName) element;
858
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
859
                    handleSource(state, element, table);
860
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
861
                    if (commonName.getName() != null) {
862
                        csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();
863
                    }
864
                    if (commonName.getLanguage() != null) {
865
                        csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();
866
                    }
867
                    if (commonName.getArea() != null) {
868
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();
869
                    }
870
                    state.getProcessor().put(table, commonName, csvLine);
871
                } else if (element instanceof TextData){
872
                    String[] csvLine = new String[table.getSize()];
873
                    TextData commonName = (TextData) element;
874
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
875
                    handleSource(state, element, table);
876
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
877
                    if (commonName.getMultilanguageText() != null) {
878
                        csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = createMultilanguageString(commonName.getMultilanguageText());
879
                    }
880
                    state.getProcessor().put(table, commonName, csvLine);
881
                } else {
882
                    state.getResult()
883
                            .addError("The common name description for the taxon " + taxon.getUuid()
884
                                    + " is not of type common name. Could not be exported. UUID of the description element: "
885
                                    + element.getUuid());
886
                }
887
            } catch (Exception e) {
888
                state.getResult().addException(e, "An unexpected error occurred when handling single common name "
889
                        + cdmBaseStr(element) + " - "+taxon.getTitleCache()+ ": " + e.getMessage());
890
            }
891
        }
892
    }
893

    
894
    private String getTitleCache(IIdentifiableEntity identEntity) {
895
        if (identEntity == null) {
896
            return "";
897
        }
898
        // TODO refresh?
899
        return identEntity.getTitleCache();
900
    }
901

    
902
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
903
        if (cdmBase == null) {
904
            return "";
905
        }
906
        // TODO make configurable
907
        return cdmBase.getUuid().toString();
908
    }
909

    
910
    private void handleSynonym(CdmLightExportState state, Synonym synonym, int index) {
911
        try {
912
            if (isUnpublished(state.getConfig(), synonym)) {
913
                return;
914
            }
915
            TaxonName name = synonym.getName();
916
            handleName(state, name, synonym.getAcceptedTaxon());
917

    
918
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
919
            String[] csvLine = new String[table.getSize()];
920

    
921
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, synonym);
922
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, synonym.getAcceptedTaxon());
923
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
924
            if (synonym.getSec() != null && !state.getReferenceStore().contains(synonym.getSec().getUuid())) {
925
                handleReference(state, synonym.getSec());
926
            }
927
            csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = synonym.getAppendedPhrase();
928
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synonym.getSec());
929
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synonym.getSec());
930
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = synonym.isPublish() ? "1" : "0";
931
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = "0";
932
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = "0";
933
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = "0";
934
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
935
            state.getProcessor().put(table, synonym, csvLine);
936
        } catch (Exception e) {
937
            state.getResult().addException(e, "An unexpected error occurred when handling synonym "
938
                    + cdmBaseStr(synonym) + ": " + e.getMessage());
939
        }
940
    }
941

    
942
    /**
943
     * Handles misapplied names (including pro parte and partial as well as pro
944
     * parte and partial synonyms
945
     */
946
    private void handleProPartePartialMisapplied(CdmLightExportState state, Taxon taxon, Taxon accepted, boolean isProParte, boolean isMisapplied, int index) {
947
        try {
948
            Taxon ppSyonym = taxon;
949
            if (isUnpublished(state.getConfig(), ppSyonym)) {
950
                return;
951
            }
952
            TaxonName name = ppSyonym.getName();
953
            handleName(state, name, accepted);
954

    
955
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
956
            String[] csvLine = new String[table.getSize()];
957

    
958
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, ppSyonym);
959
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, accepted);
960
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
961

    
962
            Reference secRef = ppSyonym.getSec();
963

    
964
            if (secRef != null && !state.getReferenceStore().contains(secRef.getUuid())) {
965
                handleReference(state, secRef);
966
            }
967
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
968
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
969
            Set<TaxonRelationship> rels = accepted.getTaxonRelations(ppSyonym);
970
            TaxonRelationship rel = null;
971
            boolean isPartial = false;
972
            if (rels.size() == 1){
973
                rel = rels.iterator().next();
974

    
975
            }else if (rels.size() > 1){
976
                Iterator<TaxonRelationship> iterator = rels.iterator();
977
                while (iterator.hasNext()){
978
                    rel = iterator.next();
979
                    if (isProParte && rel.getType().isAnySynonym()){
980
                        break;
981
                    } else if (isMisapplied && rel.getType().isAnyMisappliedName()){
982
                        break;
983
                    }else{
984
                        rel = null;
985
                    }
986
                }
987
            }
988
            if (rel != null){
989
                Reference synSecRef = rel.getCitation();
990
                if (synSecRef != null && !state.getReferenceStore().contains(synSecRef.getUuid())) {
991
                    handleReference(state, synSecRef);
992
                }
993
                csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
994
                csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
995
                isProParte = rel.getType().isProParte();
996
                isPartial = rel.getType().isPartial();
997

    
998
            }else{
999
                state.getResult().addWarning("An unexpected error occurred when handling "
1000
                        + "pro parte/partial synonym or misapplied name  " + cdmBaseStr(taxon) );
1001
            }
1002

    
1003
            // pro parte type
1004

    
1005
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = isProParte ? "1" : "0";
1006
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = isPartial ? "1" : "0";
1007
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = isMisapplied ? "1" : "0";
1008
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
1009
            state.getProcessor().put(table, ppSyonym, csvLine);
1010
        } catch (Exception e) {
1011
            state.getResult().addException(e, "An unexpected error occurred when handling "
1012
                    + "pro parte/partial synonym or misapplied name  " + cdmBaseStr(taxon) + ": " + e.getMessage());
1013
        }
1014

    
1015
    }
1016

    
1017
    private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon){
1018
        handleName(state, name, acceptedTaxon, false);
1019
    }
1020

    
1021
    private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon, boolean acceptedName) {
1022
        if (name == null || state.getNameStore().containsKey(name.getId())) {
1023
            return;
1024
        }
1025
        try {
1026
            Rank rank = name.getRank();
1027
            CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
1028
            name = HibernateProxyHelper.deproxy(name);
1029
            state.getNameStore().put(name.getId(), name.getUuid());
1030
            String[] csvLine = new String[table.getSize()];
1031

    
1032
            csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
1033
            if (name.getLsid() != null) {
1034
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
1035
            } else {
1036
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
1037
            }
1038

    
1039
            handleIdentifier(state, name);
1040
            handleDescriptions(state, name);
1041

    
1042
            csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
1043
            if (rank != null) {
1044
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
1045
                if (rank.isInfraGeneric()) {
1046
                    try {
1047
                        csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank()
1048
                                .getInfraGenericMarker();
1049
                    } catch (UnknownCdmTypeException e) {
1050
                        state.getResult().addError("Infrageneric marker expected but not available for rank "
1051
                                + name.getRank().getTitleCache());
1052
                    }
1053
                }
1054
                if (rank.isInfraSpecific()) {
1055
                    csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
1056
                }
1057
            } else {
1058
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
1059
            }
1060
            if (name.isProtectedTitleCache()) {
1061
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
1062
            } else {
1063
                // TODO: adapt the tropicos titlecache creation
1064
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
1065
            }
1066

    
1067

    
1068
            if (!state.getConfig().isAddHTML()) {
1069
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = name.getFullTitleCache();
1070
            } else {
1071
                List<TaggedText> taggedFullTitleCache = name.getTaggedFullTitle();
1072
                List<TaggedText> taggedName = name.getTaggedName();
1073

    
1074
                String fullTitleWithHtml = createNameWithItalics(taggedFullTitleCache);
1075
                // TODO: adapt the tropicos titlecache creation
1076
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = fullTitleWithHtml.trim();
1077
            }
1078

    
1079
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
1080
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
1081

    
1082
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
1083
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
1084

    
1085
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
1086

    
1087
            csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = name.getAppendedPhrase();
1088

    
1089
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
1090
            if (name.getBasionymAuthorship() != null) {
1091
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
1092
                    handleAuthor(state, name.getBasionymAuthorship());
1093
                }
1094
            }
1095
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state,
1096
                    name.getExBasionymAuthorship());
1097
            if (name.getExBasionymAuthorship() != null) {
1098
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
1099
                    handleAuthor(state, name.getExBasionymAuthorship());
1100
                }
1101

    
1102
            }
1103
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,
1104
                    name.getCombinationAuthorship());
1105
            if (name.getCombinationAuthorship() != null) {
1106
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
1107
                    handleAuthor(state, name.getCombinationAuthorship());
1108
                }
1109
            }
1110
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state,
1111
                    name.getExCombinationAuthorship());
1112
            if (name.getExCombinationAuthorship() != null) {
1113
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
1114
                    handleAuthor(state, name.getExCombinationAuthorship());
1115
                }
1116

    
1117
            }
1118

    
1119
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
1120

    
1121
            Reference nomRef = name.getNomenclaturalReference();
1122

    
1123
            NomenclaturalSource nomenclaturalSource = name.getNomenclaturalSource();
1124
            if (nomenclaturalSource != null &&nomenclaturalSource.getNameUsedInSource() != null){
1125
                handleName(state, nomenclaturalSource.getNameUsedInSource(), null);
1126
                csvLine[table.getIndex(CdmLightExportTable.NAME_USED_IN_SOURCE)] = getId(state, nomenclaturalSource.getNameUsedInSource());
1127
            }
1128

    
1129
            if (nomRef != null) {
1130
                if (!state.getReferenceStore().contains(nomRef.getUuid())) {
1131
                    handleReference(state, nomRef);
1132
                }
1133
                csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
1134
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
1135
                if (nomRef.getVolume() != null) {
1136
                    csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
1137
                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
1138
                }
1139
                if (nomRef.getDatePublished() != null) {
1140
                    csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
1141
                    csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
1142
                    csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = nomRef.getDatePublished()
1143
                            .getVerbatimDate();
1144
                }
1145
                if (name.getNomenclaturalMicroReference() != null) {
1146
                    csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
1147
                }
1148
                nomRef = HibernateProxyHelper.deproxy(nomRef);
1149
                if (nomRef.getInReference() != null) {
1150
                    Reference inReference = nomRef.getInReference();
1151
                    if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null) {
1152
                        csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference
1153
                                .getDatePublishedString();
1154
                        csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished()
1155
                                .getYear();
1156
                    }
1157
                    if (nomRef.getVolume() == null && inReference.getVolume() != null) {
1158
                        csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
1159
                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
1160
                    }
1161
                    if (inReference.getInReference() != null) {
1162
                        inReference = inReference.getInReference();
1163
                    }
1164
                    if (inReference.getAbbrevTitle() == null) {
1165
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1166
                                .Nz(inReference.getTitle());
1167
                    } else {
1168
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1169
                                .Nz(inReference.getAbbrevTitle());
1170
                    }
1171
                    if (inReference.getTitle() == null) {
1172
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils
1173
                                .Nz(inReference.getAbbrevTitle()!= null? inReference.getAbbrevTitle(): inReference.getTitleCache());
1174
                    } else {
1175
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
1176
                    }
1177

    
1178
                    TeamOrPersonBase<?> author = inReference.getAuthorship();
1179
                    if (author != null
1180
                            && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))) {
1181
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1182
                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitleCache());
1183
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1184
                                .Nz(author.getTitleCache());
1185
                    } else {
1186
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1187
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1188
                    }
1189
                } else {
1190
                    if (nomRef.getAbbrevTitle() == null) {
1191
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1192
                                .Nz(nomRef.getTitle()!= null? nomRef.getTitle():nomRef.getAbbrevTitleCache());
1193
                    } else {
1194
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1195
                                .Nz(nomRef.getAbbrevTitle());
1196
                    }
1197
                    if (nomRef.getTitle() == null) {
1198
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] =  CdmUtils
1199
                                .Nz(nomRef.getAbbrevTitle()!= null? nomRef.getAbbrevTitle(): nomRef.getTitleCache());
1200
                    } else {
1201
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
1202
                    }
1203
                    TeamOrPersonBase<?> author = nomRef.getAuthorship();
1204
                    if (author != null) {
1205
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1206
                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitleCache());
1207
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1208
                                .Nz(author.getTitleCache());
1209
                    } else {
1210
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1211
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1212
                    }
1213

    
1214
                }
1215
            } else {
1216
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
1217
            }
1218

    
1219
            /*
1220
             * Collation
1221
             *
1222
             * Detail
1223
             *
1224
             * TitlePageYear
1225
             */
1226
            String protologueUriString = extractProtologueURIs(state, name);
1227

    
1228
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
1229
            Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1230
            List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1231
            for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1232
                if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1233

    
1234
                    if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1235
                        Set<IdentifiableSource> sources =  typeDesignation.getSources();
1236
                        boolean isProtologue = false;
1237
                        if (sources != null && !sources.isEmpty()){
1238
                            IdentifiableSource source = sources.iterator().next();
1239
                            if (name.getNomenclaturalReference() != null){
1240
                                isProtologue = source.getCitation() != null? source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid()): false;
1241
                            }
1242
                        }
1243
                        if (isProtologue){
1244
                            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_TYPE_STATEMENT)] = ((TextualTypeDesignation) typeDesignation)
1245
                                    .getPreferredText(Language.DEFAULT());
1246
                        }else{
1247
                            textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1248
                        }
1249

    
1250
                    } else {
1251
                        textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1252
                    }
1253
                } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1254
                    SpecimenTypeDesignation specimenType = HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class);
1255
                    specimenTypeDesignations.add(specimenType);
1256
                    handleSpecimenType(state, specimenType);
1257

    
1258

    
1259
                }else if (typeDesignation instanceof NameTypeDesignation){
1260
                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
1261
                }
1262
            }
1263
            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
1264
            HTMLTagRules rules = new HTMLTagRules();
1265
            rules.addRule(TagEnum.name, "i");
1266
            String test = manager.print(false, false, false, rules);;
1267
            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false, rules);
1268

    
1269
            StringBuilder stringbuilder = new StringBuilder();
1270
            int i = 1;
1271
            for (TextualTypeDesignation typeDesignation : textualTypeDesignations) {
1272
                stringbuilder.append(typeDesignation.getPreferredText(Language.DEFAULT()));
1273
                if (typeDesignation.getSources() != null && !typeDesignation.getSources().isEmpty() ){
1274
                    stringbuilder.append( " [");
1275
                    int index = 1;
1276
                    for (IdentifiableSource source: typeDesignation.getSources()){
1277
                        if (source.getCitation() != null){
1278
                            stringbuilder.append(OriginalSourceFormatter.INSTANCE.format(source));
1279
                        }
1280
                        if (index < typeDesignation.getSources().size()) {
1281
                            stringbuilder.append( ", ");
1282
                        }
1283
                        index++;
1284
                    }
1285
                    stringbuilder.append( "]");
1286
                }
1287
                if (i < textualTypeDesignations.size()) {
1288
                    stringbuilder.append( "; ");
1289
                } else {
1290
                    stringbuilder.append(".");
1291
                }
1292
                i++;
1293
            }
1294
            csvLine[table.getIndex(CdmLightExportTable.TYPE_STATEMENT)] = stringbuilder.toString();
1295

    
1296

    
1297
            if (name.getStatus() == null || name.getStatus().isEmpty()) {
1298
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
1299
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
1300
            } else {
1301

    
1302
                String statusStringAbbrev = extractStatusString(state, name, true);
1303
                String statusString = extractStatusString(state, name, false);
1304

    
1305
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
1306
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
1307
            }
1308

    
1309
            HomotypicalGroup group = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
1310

    
1311
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
1312
            List<TaxonName> typifiedNames = new ArrayList<>();
1313
            if (acceptedTaxon != null){
1314
                HomotypicGroupTaxonComparator comparator = new HomotypicGroupTaxonComparator(acceptedTaxon);
1315
                List<Synonym> synonymsInGroup = null;
1316
                if (group.equals(acceptedTaxon.getHomotypicGroup())){
1317
                    synonymsInGroup = acceptedTaxon.getHomotypicSynonymsByHomotypicGroup(comparator);
1318
                    typifiedNames.add(name);
1319
                }else{
1320
                    synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group, comparator);
1321
                }
1322

    
1323
                synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(HibernateProxyHelper.deproxy(synonym.getName(), TaxonName.class)));
1324

    
1325
            }else{
1326
                typifiedNames.addAll(group.getTypifiedNames());
1327
            }
1328

    
1329

    
1330
            Integer seqNumber = typifiedNames.indexOf(name);
1331
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1332
            state.getProcessor().put(table, name, csvLine);
1333
            handleNameRelationships(state, name);
1334

    
1335
        } catch (Exception e) {
1336
            state.getResult().addException(e,
1337
                    "An unexpected error occurred when handling the name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1338

    
1339
            e.printStackTrace();
1340
        }
1341
    }
1342

    
1343
    /**
1344
     * @param specimenType
1345
     */
1346
    private void handleSpecimenType_(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1347
        if (specimenType.getTypeSpecimen() != null){
1348
            DerivedUnit specimen =  specimenType.getTypeSpecimen();
1349
            if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1350
               handleSpecimen(state, specimen);
1351
            }
1352
        }
1353
        CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1354
        String[] csvLine = new String[table.getSize()];
1355
        //TYPE_ID, SPECIMEN_FK, TYPE_VERBATIM_CITATION, TYPE_STATUS, TYPE_DESIGNATED_BY_STRING, TYPE_DESIGNATED_BY_REF_FK};
1356
        //Specimen_Fk und den Typusangaben (Art des Typus [holo, lecto, etc.], Quelle, Designation-Quelle, +
1357
        Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1358
        for (TaxonName name: typifiedNames){
1359
            csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1360
            csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
1361
            csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1362
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1363
            if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1364
                String sourceString = "";
1365
                int index = 0;
1366
                for (IdentifiableSource source: specimenType.getSources()){
1367
                    if (source.getCitation()!= null){
1368
                        sourceString = sourceString.concat(source.getCitation().getCitation());
1369
                    }
1370
                    index++;
1371
                    if (index != specimenType.getSources().size()){
1372
                        sourceString.concat(", ");
1373
                    }
1374
                }
1375
                csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1376
            }
1377
            if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1378
                handleReference(state, specimenType.getDesignationSource().getCitation());
1379
                csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1380
            }
1381

    
1382
            state.getProcessor().put(table, specimenType, csvLine);
1383
        }
1384
    }
1385

    
1386

    
1387
    /**
1388
     * @param specimenType
1389
     */
1390
    private void handleSpecimenType(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1391
        if (specimenType.getTypeSpecimen() != null){
1392
            DerivedUnit specimen =  specimenType.getTypeSpecimen();
1393
            if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1394
               handleSpecimen(state, specimen);
1395
            }
1396
        }
1397
        CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1398
        String[] csvLine = new String[table.getSize()];
1399

    
1400
        csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1401
        csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
1402
        csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1403
        if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1404
            String sourceString = "";
1405
            int index = 0;
1406
            List<IdentifiableSource> sources = new ArrayList<>(specimenType.getSources());
1407
            Comparator<IdentifiableSource> compareByYear = new Comparator<IdentifiableSource>() {
1408
                @Override
1409
                public int compare(IdentifiableSource o1, IdentifiableSource o2) {
1410
                    if (o1 == o2){
1411
                        return 0;
1412
                    }
1413
                    if (o1.getCitation() == null && o2.getCitation() != null){
1414
                        return -1;
1415
                    }
1416
                    if (o2.getCitation() == null && o1.getCitation() != null){
1417
                        return 1;
1418
                    }
1419
                    if (o1.getCitation().equals(o2.getCitation())){
1420
                        return 0;
1421
                    }
1422
                    if (o1.getCitation().getDatePublished() == null && o2.getCitation().getDatePublished() != null){
1423
                        return -1;
1424
                    }
1425
                    if (o1.getCitation().getDatePublished() != null && o2.getCitation().getDatePublished() == null){
1426
                        return 1;
1427
                    }
1428
                    if (o1.getCitation().getDatePublished().getYear() == null && o2.getCitation().getDatePublished().getYear() != null){
1429
                        return -1;
1430
                    }
1431
                    if (o1.getCitation().getDatePublished().getYear() != null && o2.getCitation().getDatePublished().getYear() == null){
1432
                        return 1;
1433
                    }
1434
                    return o1.getCitation().getDatePublished().getYear().compareTo(o2.getCitation().getDatePublished().getYear());
1435
                }
1436
            };
1437
            Collections.sort(sources, compareByYear);
1438
            for (IdentifiableSource source: sources){
1439
                if (source.getCitation()!= null){
1440
                    sourceString = sourceString.concat(source.getCitation().getCitation());
1441
                    handleReference(state, source.getCitation());
1442
                }
1443
                index++;
1444
                if (index <= specimenType.getSources().size()){
1445
                    sourceString = sourceString.concat("; ");
1446
                }
1447
            }
1448

    
1449
            csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1450
            if (sources.get(0).getCitation() != null ){
1451
                csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_FK)] = getId(state, sources.get(0).getCitation());
1452
            }
1453
        }
1454
        if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1455
            handleReference(state, specimenType.getDesignationSource().getCitation());
1456
            csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1457
        }
1458

    
1459

    
1460
        Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1461

    
1462
        if (typifiedNames.size() > 1){
1463
            state.getResult().addWarning("Please check the specimen type  "
1464
                    + cdmBaseStr(specimenType) + " there are more then one typified name.");
1465
        }
1466
        if (typifiedNames.iterator().hasNext()){
1467
            TaxonName name = typifiedNames.iterator().next();
1468
            csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1469
        }
1470
        state.getProcessor().put(table, specimenType, csvLine);
1471

    
1472

    
1473

    
1474

    
1475

    
1476
    }
1477

    
1478

    
1479
    private String createNameWithItalics(List<TaggedText> taggedName) {
1480

    
1481
        String fullTitleWithHtml = "";
1482
        for (TaggedText taggedText: taggedName){
1483
            if (taggedText.getType().equals(TagEnum.name)){
1484
                fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1485
            }else if (taggedText.getType().equals(TagEnum.separator)){
1486
                fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1487
            }else{
1488
                fullTitleWithHtml += taggedText.getText() + " ";
1489
            }
1490
        }
1491
        return fullTitleWithHtml;
1492
    }
1493

    
1494
    private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1495
        Set<NameRelationship> rels = name.getRelationsFromThisName();
1496
        CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1497
        String[] csvLine = new String[table.getSize()];
1498

    
1499
        for (NameRelationship rel : rels) {
1500
            NameRelationshipType type = rel.getType();
1501
            TaxonName name2 = rel.getToName();
1502
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1503
            if (!state.getNameStore().containsKey(name2.getId())) {
1504
                handleName(state, name2, null);
1505
            }
1506

    
1507
            csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1508
            csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1509
            csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1510
            state.getProcessor().put(table, name, csvLine);
1511
        }
1512

    
1513
        rels = name.getRelationsToThisName();
1514

    
1515
        csvLine = new String[table.getSize()];
1516

    
1517
        for (NameRelationship rel : rels) {
1518
            NameRelationshipType type = rel.getType();
1519
            TaxonName name2 = rel.getFromName();
1520
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1521
            if (!state.getNameStore().containsKey(name2.getId())) {
1522
                handleName(state, name2, null);
1523
            }
1524

    
1525

    
1526
        }
1527
    }
1528

    
1529
    private String createCollatation(TaxonName name) {
1530
        String collation = "";
1531
        if (name.getNomenclaturalReference() != null) {
1532
            Reference ref = name.getNomenclaturalReference();
1533
            collation = getVolume(ref);
1534
        }
1535
        if (name.getNomenclaturalMicroReference() != null) {
1536
            if (!StringUtils.isBlank(collation)) {
1537
                collation += ":";
1538
            }
1539
            collation += name.getNomenclaturalMicroReference();
1540
        }
1541

    
1542
        return collation;
1543
    }
1544

    
1545
    private String getVolume(Reference reference) {
1546
        if (reference.getVolume() != null) {
1547
            return reference.getVolume();
1548
        } else if (reference.getInReference() != null) {
1549
            if (reference.getInReference().getVolume() != null) {
1550
                return reference.getInReference().getVolume();
1551
            }
1552
        }
1553
        return null;
1554
    }
1555

    
1556
    private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1557
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1558
        String[] csvLine;
1559
        try {
1560
            if (cdmBase instanceof TaxonName){
1561
                TaxonName name = (TaxonName)cdmBase;
1562

    
1563
                try{
1564
                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1565
                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1566
                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1567
                    if (!IPNIidentifiers.isEmpty()) {
1568
                        csvLine = new String[table.getSize()];
1569
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1570
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1571
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1572
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1573
                                IPNIidentifiers);
1574
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1575
                    }
1576
                    if (!tropicosIdentifiers.isEmpty()) {
1577
                        csvLine = new String[table.getSize()];
1578
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1579
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1580
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = name.getUuid() + ", " + IPNI_NAME_IDENTIFIER;
1581
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1582
                                tropicosIdentifiers);
1583
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1584
                    }
1585
                    if (!WFOIdentifiers.isEmpty()) {
1586
                        csvLine = new String[table.getSize()];
1587
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1588
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1589
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1590
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1591
                                WFOIdentifiers);
1592
                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1593
                    }
1594
                }catch(Exception e){
1595
                    state.getResult().addWarning("Please check the identifiers for "
1596
                            + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1597

    
1598

    
1599
                }
1600
            }else{
1601
                if (cdmBase instanceof IdentifiableEntity){
1602
                    IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1603
                    List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1604
                    String tableName = null;
1605
                    if (cdmBase instanceof Reference){
1606
                        tableName = "Reference";
1607
                    }else if (cdmBase instanceof SpecimenOrObservationBase){
1608
                        tableName = "Specimen";
1609
                    }else if (cdmBase instanceof Taxon){
1610
                        tableName = "Taxon";
1611
                    }else if (cdmBase instanceof Synonym){
1612
                        tableName = "Synonym";
1613
                    }else if (cdmBase instanceof TeamOrPersonBase){
1614
                        tableName = "PersonOrTeam";
1615
                    }
1616

    
1617
                    for (Identifier identifier: identifiers){
1618
                        if (identifier.getType() == null && identifier.getIdentifier() == null){
1619
                            state.getResult().addWarning("Please check the identifiers for "
1620
                                    + cdmBaseStr(cdmBase) + " there is an empty identifier");
1621
                            continue;
1622
                        }
1623

    
1624
                        csvLine = new String[table.getSize()];
1625
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1626

    
1627
                        if (tableName != null){
1628
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1629
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1630
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1631
                            state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1632
                        }
1633
                    }
1634
                    if (cdmBase instanceof Reference ){
1635
                        Reference ref = (Reference)cdmBase;
1636
                        if (ref.getDoi() != null){
1637
                            csvLine = new String[table.getSize()];
1638
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1639
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1640
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1641
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1642
                            state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1643
                        }
1644
                    }
1645

    
1646
                    if (cdmBase instanceof TeamOrPersonBase){
1647
                        TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1648
                        if (person instanceof Person &&  ((Person)person).getOrcid() != null){
1649
                            csvLine = new String[table.getSize()];
1650
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1651
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1652
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1653
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]=  ((Person)person).getOrcid().asURI();
1654
                            state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1655
                        }
1656
                    }
1657
                }
1658
            }
1659
        } catch (Exception e) {
1660
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1661
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1662
            e.printStackTrace();
1663
        }
1664
    }
1665

    
1666
    private String extractIdentifier(Set<String> identifierSet) {
1667

    
1668
        String identifierString = "";
1669
        for (String identifier : identifierSet) {
1670
            if (!StringUtils.isBlank(identifierString)) {
1671
                identifierString += ", ";
1672
            }
1673
            identifierString += identifier;
1674
        }
1675
        return identifierString;
1676
    }
1677

    
1678
    private String extractProtologueURIs(CdmLightExportState state, TaxonName name) {
1679
        if (name.getNomenclaturalSource() != null){
1680
            Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1681
            return extractLinkUris(links.iterator());
1682
        }else{
1683
            return null;
1684
        }
1685
    }
1686

    
1687
    private String extractMediaURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1688
            Feature feature) {
1689

    
1690
        String mediaUriString = "";
1691
        Set<DescriptionElementBase> elements = new HashSet<>();
1692
        for (DescriptionBase<?> description : descriptionsSet) {
1693
            try {
1694
                if (!description.getElements().isEmpty()) {
1695
                    elements = description.getElements();
1696

    
1697
                    for (DescriptionElementBase element : elements) {
1698
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1699
                        if (entityFeature.equals(feature)) {
1700
                            if (!element.getMedia().isEmpty()) {
1701
                                List<Media> media = element.getMedia();
1702
                                for (Media mediaElement : media) {
1703
                                    Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1704
                                    mediaUriString = extractMediaUris(it);
1705
                                }
1706
                            }
1707
                        }
1708
                    }
1709
                }
1710
            } catch (Exception e) {
1711
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1712
                        + cdmBaseStr(description) + ": " + e.getMessage());
1713
            }
1714
        }
1715
        return mediaUriString;
1716
    }
1717

    
1718
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1719
        try {
1720
            if (state.getAuthorFromStore(author.getId()) != null) {
1721
                return;
1722
            }
1723
            state.addAuthorToStore(author);
1724
            handleIdentifier(state, author);
1725
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1726
            String[] csvLine = new String[table.getSize()];
1727
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1728
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
1729
            String[] csvLineMember = new String[table.getSize()];
1730
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1731
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1732
                    ? author.getTitleCache() : author.getNomenclaturalTitleCache();
1733
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1734
            author = HibernateProxyHelper.deproxy(author);
1735
            if (author instanceof Person) {
1736
                Person authorPerson = (Person) author;
1737
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1738
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1739
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1740
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1741
            } else {
1742
                // create an entry in rel table and all members in author table,
1743
                // check whether the team members already in author table
1744

    
1745
                Team authorTeam = (Team) author;
1746
                int index = 0;
1747
                for (Person member : authorTeam.getTeamMembers()) {
1748
                    csvLineRel = new String[tableAuthorRel.getSize()];
1749
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1750
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1751
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1752
                            .valueOf(index);
1753
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1754

    
1755
                    if (state.getAuthorFromStore(member.getId()) == null) {
1756
                        state.addAuthorToStore(member);
1757
                        csvLineMember = new String[table.getSize()];
1758
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1759
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1760
                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitleCache();
1761
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1762
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1763
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1764
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1765
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1766
                        state.getProcessor().put(table, member, csvLineMember);
1767
                    }
1768
                    index++;
1769
                }
1770
            }
1771
            state.getProcessor().put(table, author, csvLine);
1772
        } catch (Exception e) {
1773
            state.getResult().addException(e,
1774
                    "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1775
        }
1776
    }
1777

    
1778
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1779
        try {
1780
            Set<NomenclaturalStatus> status = name.getStatus();
1781
            if (status.isEmpty()) {
1782
                return "";
1783
            }
1784
            String statusString = "";
1785
            for (NomenclaturalStatus nameStatus : status) {
1786
                if (nameStatus != null) {
1787
                    if (abbrev) {
1788
                        if (nameStatus.getType() != null) {
1789
                            statusString += nameStatus.getType().getIdInVocabulary();
1790
                        }
1791
                    } else {
1792
                        if (nameStatus.getType() != null) {
1793
                            statusString += nameStatus.getType().getTitleCache();
1794
                        }
1795
                    }
1796
                    if (!abbrev) {
1797

    
1798
                        if (nameStatus.getRuleConsidered() != null
1799
                                && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1800
                            statusString += ": " + nameStatus.getRuleConsidered();
1801
                        }
1802
                        if (nameStatus.getCitation() != null) {
1803
                            String shortCitation = OriginalSourceFormatter.INSTANCE.format(nameStatus.getCitation(), null);
1804
                            statusString += " (" + shortCitation + ")";
1805
                        }
1806
//                        if (nameStatus.getCitationMicroReference() != null
1807
//                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1808
//                            statusString += " " + nameStatus.getCitationMicroReference();
1809
//                        }
1810
                    }
1811
                    statusString += " ";
1812
                }
1813
            }
1814
            return statusString;
1815
        } catch (Exception e) {
1816
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1817
                    + cdmBaseStr(name) + ": " + e.getMessage());
1818
            return "";
1819
        }
1820
    }
1821

    
1822
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, Taxon acceptedTaxon, int sortIndex) {
1823
        try {
1824
            state.addHomotypicalGroupToStore(group);
1825
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1826
            String[] csvLine = new String[table.getSize()];
1827
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(sortIndex);
1828
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1829

    
1830
            List<TaxonName> typifiedNames = new ArrayList<>();
1831
            if (acceptedTaxon != null){
1832
                List<Synonym> synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group);
1833
                if (group.equals(acceptedTaxon.getHomotypicGroup())){
1834
                    typifiedNames.add(acceptedTaxon.getName());
1835
                }
1836
                synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(CdmBase.deproxy(synonym.getName())));
1837
            }
1838

    
1839

    
1840
            TaxonName firstname = null;
1841
            for (TaxonName name: typifiedNames){
1842
                Iterator<Taxon> taxa = name.getTaxa().iterator();
1843
                while(taxa.hasNext()){
1844
                    Taxon taxon = taxa.next();
1845
                    if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1846
                        firstname = name;
1847
                        break;
1848
                    }
1849
                }
1850
            }
1851

    
1852
//            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1853
            String typifiedNamesString = "";
1854
            String typifiedNamesWithSecString = "";
1855
            String typifiedNamesWithoutAccepted = "";
1856
            String typifiedNamesWithoutAcceptedWithSec = "";
1857
            int index = 0;
1858
            for (TaxonName name : typifiedNames) {
1859
                // Concatenated output string for homotypic group (names and
1860
                // citations) + status + some name relations (e.g. “non”)
1861
                // TODO: nameRelations, which and how to display
1862
                Set<TaxonBase> taxonBases = name.getTaxonBases();
1863
                TaxonBase<?> taxonBase;
1864

    
1865
                String sec = "";
1866
                String nameString = name.getFullTitleCache();
1867
                String doubtful = "";
1868

    
1869
                if (state.getConfig().isAddHTML()){
1870
                    nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1871
                }
1872

    
1873
                Set<NameRelationship> related = name.getNameRelations();
1874
                List<NameRelationship> relatedList = new ArrayList<>(related);
1875

    
1876
                Collections.sort(relatedList, new Comparator<NameRelationship>() {
1877
                    @Override
1878
                    public int compare(NameRelationship nr1, NameRelationship nr2) {
1879
                        return nr1.getType().compareTo(nr2.getType());
1880
                    }
1881

    
1882
                });
1883

    
1884
                List<NameRelationship> nonNames = new ArrayList<>();
1885
                List<NameRelationship> otherRelationships = new ArrayList<>();
1886

    
1887
                for (NameRelationship rel: relatedList){
1888
                    //no inverse relations
1889
                    if (rel.getFromName().equals(name)){
1890
                     // alle Homonyme und inverse blocking names
1891
                        if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1892
                                || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1893
                                || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1894
                                || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))){
1895
                            nonNames.add(rel);
1896
                        }else if (!rel.getType().isBasionymRelation()){
1897
                            otherRelationships.add(rel);
1898
                        }
1899
                    }
1900
                }
1901

    
1902
                String nonRelNames = "";
1903
                String relNames = "";
1904

    
1905
                if (nonNames.size() > 0){
1906
                    nonRelNames += " [";
1907
                }
1908
                for (NameRelationship relName: nonNames){
1909
                    String label = "non ";
1910
                    TaxonName relatedName = null;
1911
                    if (relName.getFromName().equals(name)){
1912
                        relatedName = relName.getToName();
1913
                        nonRelNames += label + relatedName.getTitleCache() + " ";
1914
                    }
1915
//                    else{
1916
//                        label = relName.getType().getInverseLabel() + " ";
1917
//                        relatedName = relName.getFromName();
1918
//                        nonRelNames += label + relatedName.getTitleCache() + " ";
1919
//                    }
1920

    
1921

    
1922
                }
1923
                relNames.trim();
1924
                if (nonNames.size() > 0){
1925
                    nonRelNames = StringUtils.strip(nonRelNames, null);
1926
                    nonRelNames += "] ";
1927
                }
1928

    
1929
                if (otherRelationships.size() > 0){
1930
                    relNames += " [";
1931
                }
1932
                for (NameRelationship rel: otherRelationships){
1933
                    String label = "";
1934
                    TaxonName relatedName = null;
1935
                    if (rel.getFromName().equals(name)){
1936
                        label = rel.getType().getLabel() + " ";
1937
                        relatedName = rel.getToName();
1938
                        if (state.getConfig().isAddHTML()){
1939
                            relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
1940
                        }else{
1941
                            relNames += label + relatedName.getTitleCache();
1942
                        }
1943
                    }
1944
//                    else {
1945
//                        label = rel.getType().getInverseLabel() + " ";
1946
//                        relatedName = rel.getFromName();
1947
//                    }
1948

    
1949
                }
1950
                relNames.trim();
1951
                if (otherRelationships.size() > 0){
1952
                    relNames = StringUtils.stripEnd(relNames, null);
1953
                    relNames += "] ";
1954
                }
1955

    
1956
                String synonymSign = "";
1957
                if (index > 0){
1958
                    if (name.isInvalid()){
1959
                        synonymSign = "\u2212 ";
1960
                    }else{
1961
                        synonymSign = "\u2261 ";
1962
                    }
1963
                }else{
1964
                    if (name.isInvalid() ){
1965
                        synonymSign = "\u2212 ";
1966
                    }else{
1967
                        synonymSign = "\u003D ";
1968
                    }
1969
                }
1970
                boolean isAccepted = false;
1971

    
1972
                if (taxonBases.size() == 1){
1973
                     taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
1974

    
1975
                     if (taxonBase.getSec() != null){
1976
                         sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(taxonBase.getSecSource());
1977
                     }
1978
                     if (taxonBase.isDoubtful()){
1979
                         doubtful = "?";
1980
                     }else{
1981
                         doubtful = "";
1982
                     }
1983
                     if (taxonBase instanceof Synonym){
1984
                         if (isNotBlank(sec)){
1985
                             sec = " syn. sec. " + sec + " ";
1986
                         }else {
1987
                             sec = "";
1988
                         }
1989

    
1990
                         typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + nonRelNames + relNames;
1991
                         typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
1992
                     }else{
1993
//                         sec = "";
1994
                         if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
1995
                             isAccepted = true;
1996
                         }else {
1997
                             synonymSign = "\u003D ";
1998
                         }
1999

    
2000
                     }
2001
                     if (taxonBase.getAppendedPhrase() != null){
2002
                         if (state.getConfig().isAddHTML()){
2003
                             String taxonString = createNameWithItalics(taxonBase.getTaggedTitle()) ;
2004
                             taxonString = taxonString.replace("sec "+sec, "");
2005
                             String nameCacheWithItalics = createNameWithItalics(name.getTaggedName());
2006
                             nameString = nameString.replace(nameCacheWithItalics, taxonString);
2007
                         }
2008
                     }
2009
                }else{
2010
                    //there are names used more than once?
2011
                    for (TaxonBase<?> tb: taxonBases){
2012
                        if (tb.getSec() != null){
2013
                            sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(tb.getSecSource());
2014
                        }
2015
                        if (tb.isDoubtful()){
2016
                            doubtful = "?";
2017
                        }else{
2018
                            doubtful = "";
2019
                        }
2020
                        if (tb instanceof Synonym){
2021
                            if (StringUtils.isNotBlank(sec)){
2022
                                sec = " syn. sec. " + sec + " ";
2023
                            }else {
2024
                                sec = "";
2025
                            }
2026

    
2027
                            break;
2028
                        }else{
2029
                            sec = "";
2030
                            if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
2031
                                isAccepted = true;
2032
                                break;
2033
                            }else {
2034
                                synonymSign = "\u003D ";
2035
                            }
2036

    
2037
                        }
2038
                    }
2039
                    if (!isAccepted){
2040
                        typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + "; ";
2041
                        typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec;
2042
                        typifiedNamesWithoutAcceptedWithSec = typifiedNamesWithoutAcceptedWithSec.trim() + "; ";
2043
                    }
2044
                }
2045
                typifiedNamesString += synonymSign + doubtful + nameString + nonRelNames + relNames;
2046
                typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2047

    
2048

    
2049
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
2050

    
2051
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
2052

    
2053
                if (typifiedNamesWithoutAccepted != null && firstname != null) {
2054
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
2055
                } else {
2056
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = "";
2057
                }
2058

    
2059
                if (typifiedNamesWithoutAcceptedWithSec != null && firstname != null) {
2060
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = typifiedNamesWithoutAcceptedWithSec.trim();
2061
                } else {
2062
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = "";
2063
                }
2064
                index++;
2065
            }
2066

    
2067
            Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
2068
            List<TypeDesignationBase<?>> designationList = new ArrayList<>();
2069
            designationList.addAll(typeDesigantionSet);
2070
            Collections.sort(designationList, new TypeComparator());
2071

    
2072
            List<TaggedText> list = new ArrayList<>();
2073
            if (!designationList.isEmpty()) {
2074
                TypeDesignationSetManager manager = new TypeDesignationSetManager(group);
2075
                list.addAll(new TypeDesignationSetFormatter(true, false, false).toTaggedText(manager));
2076
            }
2077
            String typeTextDesignations = "";
2078
            //The typeDesignationManager does not handle the textual typeDesignations
2079
            for (TypeDesignationBase<?> typeDes: designationList) {
2080
            	if (typeDes instanceof TextualTypeDesignation) {
2081
            		typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
2082
            		String typeDesStateRefs = "";
2083
                    if (typeDes.getDesignationSource() != null ){
2084
                        typeDesStateRefs = "[";
2085
                        NamedSource source = typeDes.getDesignationSource();
2086
                        if (source.getCitation() != null){
2087
                            typeDesStateRefs += "fide " + OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2088
                        }
2089
                        typeDesStateRefs += "]";
2090
                    }else if (typeDes.getSources() != null && !typeDes.getSources().isEmpty()){
2091
                        typeDesStateRefs = "[";
2092
                        for (IdentifiableSource source: typeDes.getSources()) {
2093
                            if (source.getCitation() != null){
2094
                                typeDesStateRefs += "fide " +OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2095
                            }
2096
                        }
2097

    
2098
                        typeDesStateRefs += "]";
2099
                    }
2100

    
2101
            		typeTextDesignations =  typeTextDesignations + typeDesStateRefs +"; ";
2102

    
2103
            	}else if (typeDes instanceof SpecimenTypeDesignation){
2104
            	    DerivedUnit specimen =  ((SpecimenTypeDesignation)typeDes).getTypeSpecimen();
2105
            	    if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
2106
            	        handleSpecimen(state, specimen);
2107
            	    }
2108
            	}
2109
            }
2110
            if (typeTextDesignations.equals("; ")) {
2111
            	typeTextDesignations = "";
2112
            }
2113
            if (StringUtils.isNotBlank(typeTextDesignations)) {
2114
            	typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
2115
            }
2116
            String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
2117

    
2118
            if (StringUtils.isNotBlank(specimenTypeString)) {
2119
                if (!specimenTypeString.endsWith(".")) {
2120
                	specimenTypeString = specimenTypeString + ".";
2121
                }
2122
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
2123

    
2124
            } else {
2125
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
2126
            }
2127
            if (StringUtils.isNotBlank(typeTextDesignations)) {
2128
                if (!typeTextDesignations.endsWith(".")) {
2129
                	typeTextDesignations = typeTextDesignations + ".";
2130
                }
2131
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
2132

    
2133
            } else {
2134
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
2135
            }
2136
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
2137
        } catch (Exception e) {
2138
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
2139
                    + cdmBaseStr(group) + ": " + e.getMessage());
2140
        }
2141
    }
2142

    
2143
    private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup, boolean isSpecimenTypeDesignation) {
2144
        StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
2145

    
2146
        for (TaggedText text : list) {
2147
            if (text == null || text.getText() == null){
2148
                continue;  //just in case
2149
            }
2150
            if ((text.getText().equalsIgnoreCase("Type:")  //should not happen anymore
2151
                    || text.getText().equalsIgnoreCase("Nametype:")  //should not happen anymore
2152
                    || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
2153
                // do nothing
2154
            }else if (text.getType().equals(TagEnum.reference)) {
2155
                homotypicalGroupTypeDesignationString.append(text.getText());
2156
            }else if (text.getType().equals(TagEnum.name)){
2157
                if (!isSpecimenTypeDesignation){
2158
                    homotypicalGroupTypeDesignationString
2159
                        .append("<i>"+text.getText()+"</i> ");
2160
                }
2161
            }else if (text.getType().equals(TagEnum.typeDesignation) ) {
2162
                if(isSpecimenTypeDesignation){
2163
                    homotypicalGroupTypeDesignationString
2164
                        .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
2165
                }else{
2166
                    homotypicalGroupTypeDesignationString
2167
                        .append(text.getText());
2168
                }
2169

    
2170
            } else {
2171
                homotypicalGroupTypeDesignationString.append(text.getText());
2172
            }
2173
        }
2174

    
2175
        String typeDesignations = homotypicalGroupTypeDesignationString.toString();
2176
        typeDesignations = typeDesignations.trim();
2177

    
2178
        if (typeDesignations.endsWith(";")){
2179
            typeDesignations = typeDesignations.substring(0, typeDesignations.length()-1);
2180
        }
2181
        typeDesignations += ".";
2182
        typeDesignations = typeDesignations.replace("..", ".");
2183
        typeDesignations = typeDesignations.replace(". .", ".");
2184
        typeDesignations = typeDesignations.replace("; \u2261", " \u2261 ");
2185

    
2186
        if (typeDesignations.trim().equals(".")) {
2187
            typeDesignations = null;
2188
        }
2189

    
2190
        return typeDesignations;
2191
    }
2192

    
2193
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
2194
        try {
2195
            String basionymStart = "(";
2196
            String basionymEnd = ") ";
2197
            String exAuthorSeperator = " ex ";
2198
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
2199
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
2200
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
2201
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
2202

    
2203
            String combinationAuthorString = "";
2204
            if (combinationAuthor != null) {
2205
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
2206
                if (combinationAuthor instanceof Team) {
2207
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
2208
                } else {
2209
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
2210
                    combinationAuthorString = createTropicosAuthorString(person);
2211
                }
2212
            }
2213
            String exCombinationAuthorString = "";
2214
            if (exCombinationAuthor != null) {
2215
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
2216
                if (exCombinationAuthor instanceof Team) {
2217
                    exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
2218
                } else {
2219
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
2220
                    exCombinationAuthorString = createTropicosAuthorString(person);
2221
                }
2222
            }
2223

    
2224
            String basionymAuthorString = "";
2225
            if (basionymAuthor != null) {
2226
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
2227
                if (basionymAuthor instanceof Team) {
2228
                    basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
2229
                } else {
2230
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
2231
                    basionymAuthorString = createTropicosAuthorString(person);
2232
                }
2233
            }
2234

    
2235
            String exBasionymAuthorString = "";
2236

    
2237
            if (exBasionymAuthor != null) {
2238
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
2239
                if (exBasionymAuthor instanceof Team) {
2240
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
2241

    
2242
                } else {
2243
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
2244
                    exBasionymAuthorString = createTropicosAuthorString(person);
2245
                }
2246
            }
2247
            String completeAuthorString = name.getNameCache() + " ";
2248

    
2249
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2250
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
2251
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
2252
                    ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
2253
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
2254
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2255
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
2256
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
2257
                    ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
2258
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
2259
                    : "";
2260

    
2261
            return completeAuthorString;
2262
        } catch (Exception e) {
2263
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
2264
                    + cdmBaseStr(name) + ": " + e.getMessage());
2265
            return null;
2266
        }
2267
    }
2268

    
2269
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
2270
        String combinationAuthorString;
2271
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
2272
        Team tempTeam = Team.NewInstance();
2273
        for (Person teamMember : team.getTeamMembers()) {
2274
            combinationAuthorString = createTropicosAuthorString(teamMember);
2275
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
2276
            tempTeam.addTeamMember(tempPerson);
2277
        }
2278
        combinationAuthorString = tempTeam.generateTitle();
2279
        return combinationAuthorString;
2280
    }
2281

    
2282
    private String createTropicosAuthorString(Person teamMember) {
2283
        String nomAuthorString = "";
2284
        String[] splittedAuthorString = null;
2285
        if (teamMember == null) {
2286
            return nomAuthorString;
2287
        }
2288

    
2289
        if (teamMember.getGivenName() != null) {
2290
            String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
2291
            splittedAuthorString = givenNameString.split("\\s");
2292
            for (String split : splittedAuthorString) {
2293
                if (!StringUtils.isBlank(split)) {
2294
                    nomAuthorString += split.substring(0, 1);
2295
                    nomAuthorString += ".";
2296
                }
2297
            }
2298
        }
2299
        if (teamMember.getFamilyName() != null) {
2300
            String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
2301
            splittedAuthorString = familyNameString.split("\\s");
2302
            for (String split : splittedAuthorString) {
2303
                nomAuthorString += " " + split;
2304
            }
2305
        }
2306
        if (isBlank(nomAuthorString.trim())) {
2307
            if (teamMember.getTitleCache() != null) {
2308
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
2309
                splittedAuthorString = titleCacheString.split("\\s");
2310
            } else {
2311
                splittedAuthorString = new String[0];
2312
            }
2313

    
2314
            int index = 0;
2315
            for (String split : splittedAuthorString) {
2316
                if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
2317
                    nomAuthorString += split;
2318
                } else {
2319
                    nomAuthorString = nomAuthorString + " " + split;
2320
                }
2321
                index++;
2322
            }
2323
        }
2324
        return nomAuthorString.trim();
2325
    }
2326

    
2327
    private void handleReference(CdmLightExportState state, Reference reference) {
2328
        try {
2329
            state.addReferenceToStore(reference);
2330
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
2331
            reference = HibernateProxyHelper.deproxy(reference);
2332

    
2333
            handleIdentifier(state, reference);
2334
            String[] csvLine = new String[table.getSize()];
2335
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
2336
            // TODO short citations correctly
2337
            String shortCitation = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(reference, null); // Should be Author(year) like in Taxon.sec
2338
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
2339
            // TODO get preferred title
2340
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
2341
                    ? reference.getTitleCache() : reference.getTitle();
2342
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
2343
                    ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
2344
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
2345
            // TBC
2346
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
2347
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
2348
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
2349
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
2350
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
2351
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
2352
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
2353
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
2354
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
2355
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
2356
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
2357
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
2358

    
2359
            if (reference.getAuthorship() != null) {
2360
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
2361
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
2362
            }
2363

    
2364
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
2365
            if (reference.getInReference() != null
2366
                    && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
2367
                handleReference(state, reference.getInReference());
2368
            }
2369
            if (reference.getInstitution() != null) {
2370
                csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
2371
            }
2372
            if (reference.getLsid() != null) {
2373
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
2374
            }
2375
            if (reference.getSchool() != null) {
2376
                csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
2377
            }
2378
            if (reference.getUri() != null) {
2379
                csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
2380
            }
2381
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
2382

    
2383
            state.getProcessor().put(table, reference, csvLine);
2384
        } catch (Exception e) {
2385
            state.getResult().addException(e, "An unexpected error occurred when handling reference "
2386
                    + cdmBaseStr(reference) + ": " + e.getMessage());
2387
        }
2388
    }
2389

    
2390
    private String createFullAuthorship(Reference reference) {
2391
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
2392
        String fullAuthorship = "";
2393
        if (authorship == null) {
2394
            return null;
2395
        }
2396
        authorship = HibernateProxyHelper.deproxy(authorship);
2397
        if (authorship instanceof Person) {
2398
            fullAuthorship = ((Person) authorship).getTitleCache();
2399

    
2400
        } else if (authorship instanceof Team) {
2401

    
2402
            Team authorTeam = (Team)authorship;
2403
            fullAuthorship = authorTeam.getCacheStrategy().getTitleCache(authorTeam);
2404
        }
2405
        return fullAuthorship;
2406
    }
2407

    
2408
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
2409
        try {
2410
            state.addSpecimenToStore(specimen);
2411
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
2412
            String specimenId = getId(state, specimen);
2413
            String[] csvLine = new String[table.getSize()];
2414

    
2415
            /*
2416
             * SpecimenCitation = “El Salvador, Municipio La Libertad, San
2417
             * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
2418
             * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
2419
             * HerbariumCode
2420
             *
2421
             */
2422

    
2423
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
2424
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
2425
            Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
2426
            if (fieldUnits.size() == 1) {
2427
                Iterator<FieldUnit> iterator = fieldUnits.iterator();
2428
                if (iterator.hasNext()){
2429
                    FieldUnit fieldUnit = iterator.next();
2430
                    csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
2431
                }
2432
            }
2433
            if (specimen.isInstanceOf(DerivedUnit.class)){
2434
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
2435
                if (!StringUtils.isBlank(derivedUnit.getBarcode())){
2436
                    csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
2437
                }
2438
                if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
2439
                    csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
2440
                }
2441
                if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
2442
                    csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
2443
                }
2444
            }
2445

    
2446
            csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
2447
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
2448
                    specimen.getDescriptions(), Feature.IMAGE());
2449
            if (specimen instanceof DerivedUnit) {
2450
                DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(specimen, DerivedUnit.class);
2451
                if (derivedUnit.getCollection() != null) {
2452
                    csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
2453
                            .getCode();
2454
                }
2455

    
2456
                if (specimen instanceof MediaSpecimen) {
2457
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
2458
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
2459
                    String mediaUris = extractMediaUris(it);
2460
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
2461

    
2462
                }
2463

    
2464
                if (derivedUnit.getDerivedFrom() != null) {
2465
                    for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
2466
                        // TODO: What to do if there are more then one
2467
                        // FieldUnit??
2468
                        if (original instanceof FieldUnit) {
2469
                            FieldUnit fieldUnit = (FieldUnit) original;
2470
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
2471

    
2472
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
2473
                            if (gathering != null) {
2474
                                if (gathering.getLocality() != null) {
2475
                                    csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
2476
                                            .getText();
2477
                                }
2478
                                if (gathering.getCountry() != null) {
2479
                                    csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
2480
                                            .getLabel();
2481
                                }
2482
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2483
                                        state, gathering, fieldUnit);
2484

    
2485
                                if (gathering.getGatheringDate() != null) {
2486
                                    csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2487
                                            .getGatheringDate().toString();
2488
                                }
2489
                                if (!gathering.getCollectingAreas().isEmpty()) {
2490
                                    int index = 0;
2491
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2492
                                    for (NamedArea area : gathering.getCollectingAreas()) {
2493
                                        if (index == 0) {
2494
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2495
                                                    .getLevel().getLabel():"";
2496
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2497
                                        }
2498
                                        if (index == 1) {
2499
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2500
                                                    .getLevel().getLabel():"";
2501
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2502
                                        }
2503
                                        if (index == 2) {
2504
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2505
                                                    .getLevel().getLabel():"";
2506
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2507
                                        }
2508
                                        if (index == 3) {
2509
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2510
                                            break;
2511
                                        }
2512
                                        index++;
2513
                                    }
2514
                                }
2515
                            }
2516
                        }
2517
                    }
2518
                } else {
2519
                    state.getResult().addError("The specimen with uuid " + specimen.getUuid()
2520
                            + " is not an DerivedUnit. Could not be exported.");
2521
                }
2522
            }
2523

    
2524
            state.getProcessor().put(table, specimen, csvLine);
2525
        } catch (Exception e) {
2526
            state.getResult().addException(e, "An unexpected error occurred when handling specimen "
2527
                    + cdmBaseStr(specimen) + ": " + e.getMessage());
2528
        }
2529
    }
2530

    
2531
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
2532

    
2533
        String mediaUriString = "";
2534
        boolean first = true;
2535
        while (it.hasNext()) {
2536
            MediaRepresentation rep = it.next();
2537
            List<MediaRepresentationPart> parts = rep.getParts();
2538
            for (MediaRepresentationPart part : parts) {
2539
                if (first) {
2540
                    if (part.getUri() != null) {
2541
                        mediaUriString += part.getUri().toString();
2542
                        first = false;
2543
                    }
2544
                } else {
2545
                    if (part.getUri() != null) {
2546
                        mediaUriString += ", " + part.getUri().toString();
2547
                    }
2548
                }
2549
            }
2550
        }
2551

    
2552
        return mediaUriString;
2553
    }
2554

    
2555
    private String extractLinkUris(Iterator<ExternalLink> it) {
2556

    
2557
        String linkUriString = "";
2558
        boolean first = true;
2559
        while (it.hasNext()) {
2560
            ExternalLink link = it.next();
2561
            if (first) {
2562
                if (link.getUri() != null) {
2563
                    linkUriString += link.getUri().toString();
2564
                    first = false;
2565
                }
2566
            } else {
2567
                if (link.getUri() != null) {
2568
                    linkUriString += ", " + link.getUri().toString();
2569
                }
2570
            }
2571
        }
2572
        return linkUriString;
2573
    }
2574

    
2575
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2576
        try {
2577
            String collectorString = "";
2578
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2579
            if (gathering.getCollector() != null) {
2580
                if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2581

    
2582
                    Person primaryCollector = fieldUnit.getPrimaryCollector();
2583
                    if (collectorA instanceof Team) {
2584
                        Team collectorTeam = (Team) collectorA;
2585
                        boolean isFirst = true;
2586
                        for (Person member : collectorTeam.getTeamMembers()) {
2587
                            if (!isFirst) {
2588
                                collectorString += "; ";
2589
                            }
2590
                            if (member.equals(primaryCollector)) {
2591
                                // highlight
2592
                                collectorString += "<b>" + member.getTitleCache() + "</b>";
2593
                            } else {
2594
                                collectorString += member.getTitleCache();
2595
                            }
2596
                        }
2597
                    }
2598
                } else {
2599
                    collectorString = collectorA.getTitleCache();
2600
                }
2601
            }
2602
            return collectorString;
2603
        } catch (Exception e) {
2604
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2605
                    + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2606
            return "";
2607
        }
2608
    }
2609

    
2610
    /**
2611
     * Returns a string representation of the {@link CdmBase cdmBase} object for
2612
     * result messages.
2613
     */
2614
    private String cdmBaseStr(CdmBase cdmBase) {
2615
        if (cdmBase == null) {
2616
            return "-no object available-";
2617
        } else {
2618
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2619
        }
2620
    }
2621

    
2622
    @Override
2623
    protected boolean doCheck(CdmLightExportState state) {
2624
        return false;
2625
    }
2626

    
2627
    @Override
2628
    protected boolean isIgnore(CdmLightExportState state) {
2629
        return false;
2630
    }
2631

    
2632
}
(1-1/6)