Project

General

Profile

Download (135 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.HashMap;
17
import java.util.HashSet;
18
import java.util.Iterator;
19
import java.util.List;
20
import java.util.Map;
21
import java.util.Set;
22
import java.util.UUID;
23

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

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

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

    
116
    private static final long serialVersionUID = 2518643632756927053L;
117

    
118
    @Autowired
119
    IEditGeoService geoService;
120

    
121
    public CdmLightClassificationExport() {
122
        super();
123
        this.ioName = this.getClass().getSimpleName();
124
    }
125

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

    
132
    @Override
133
    protected void doInvoke(CdmLightExportState state) {
134
        try {
135

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

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

    
150
            handleMetaData(state);
151
            monitor.subTask("Start partitioning");
152

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

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

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

    
181
                state.getNodeChildrenMap().clear();
182
                for (OrderHelper order : state.getOrderHelperMap().values()) {
183
                    setOrderIndex(state, order);
184
                }
185
            }
186

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

    
195
    private void setOrderIndex(CdmLightExportState state, OrderHelper order) {
196

    
197
        if (order.getTaxonUuid() != null
198
                && state.getProcessor().hasRecord(CdmLightExportTable.TAXON, order.getTaxonUuid().toString())) {
199
            String[] csvLine = state.getProcessor().getRecord(CdmLightExportTable.TAXON,
200
                    order.getTaxonUuid().toString());
201
            csvLine[CdmLightExportTable.TAXON.getIndex(CdmLightExportTable.SORT_INDEX)] = String
202
                    .valueOf(order.getOrderIndex());
203
        }
204

    
205
        if (order.getChildren() == null) {
206
            return;
207
        }
208
        for (OrderHelper helper : order.getChildren()) {
209
            setOrderIndex(state, helper);
210
        }
211
    }
212

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

    
231
            if (state.getNodeChildrenMap().get(child.getUuid()) != null) {
232
                children = state.getNodeChildrenMap().get(child.getUuid());
233
                helperChild.addChildren(createOrderHelper(children, state));
234
            }
235
            childrenHelper.add(helperChild);
236
        }
237
        return childrenHelper;
238
    }
239

    
240
    private void handleTaxonNode(CdmLightExportState state, TaxonNode taxonNode) {
241

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

    
259
                    // add root to node map
260

    
261
                }
262
                TaxonNodeDto rootDto = new TaxonNodeDto(root);
263
                UUID parentUuid = root.getParent() != null ? root.getParent().getUuid()
264
                        : state.getClassificationUUID(root);
265
                List<TaxonNodeDto> children = state.getNodeChildrenMap().get(parentUuid);
266
                if (children != null && !children.contains(rootDto)) {
267
                    state.getNodeChildrenMap().get(parentUuid).add(rootDto);
268
                } else if (state.getNodeChildrenMap().get(parentUuid) == null) {
269
                    List<TaxonNodeDto> rootList = new ArrayList<>();
270
                    rootList.add(rootDto);
271
                    state.getNodeChildrenMap().put(parentUuid, rootList);
272

    
273
                }
274
                if (root.hasTaxon()) {
275
                    handleTaxon(state, root);
276

    
277
                }
278
            } catch (Exception e) {
279
                state.getResult().addException(e, "An unexpected error occurred when handling taxonNode "
280
                        + taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
281
            }
282
        }
283
    }
284

    
285
    private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
286
        try {
287

    
288
            if (taxonNode == null) {
289
                state.getResult().addError("The taxonNode was null.", "handleTaxon");
290
                state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
291
                return;
292
            }
293
            if (taxonNode.getTaxon() == null) {
294
                state.getResult().addError("There was a taxon node without a taxon: " + taxonNode.getUuid(),
295
                        "handleTaxon");
296
                state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
297
            } else {
298
                Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon());
299

    
300
                try {
301
                    TaxonName name = taxon.getName();
302
                    handleName(state, name, taxon, true);
303
                    HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
304
                    int index = 0;
305
                    int homotypicGroupIndex = 0;
306
                    handleHomotypicalGroup(state, homotypicGroup, taxon, homotypicGroupIndex);
307
                    homotypicGroupIndex++;
308
                    for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
309
                        handleSynonym(state, syn, index);
310
                        index++;
311
                    }
312
                    List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
313
                    for (HomotypicalGroup group: heterotypicHomotypicGroups){
314
                        handleHomotypicalGroup(state, group, taxon, homotypicGroupIndex);
315
                        for (Synonym syn : taxon.getSynonymsInGroup(group)) {
316
                            handleSynonym(state, syn, index);
317
                            index++;
318
                        }
319
                        homotypicGroupIndex++;
320
                    }
321

    
322
                    index = 0;
323
                    for (Taxon tax : taxon.getAllProParteSynonyms()) {
324
                        handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
325
                        index++;
326
                    }
327

    
328

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

    
334
                    CdmLightExportTable table = CdmLightExportTable.TAXON;
335
                    String[] csvLine = new String[table.getSize()];
336

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

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

    
377
                    csvLine[table.getIndex(CdmLightExportTable.UNPLACED)] = taxonNode.isUnplaced() ? "1" : "0";
378
                    csvLine[table.getIndex(CdmLightExportTable.DOUBTFUL)] = taxonNode.isDoubtful() ? "1" : "0";
379
                    state.getProcessor().put(table, taxon, csvLine);
380
                    handleDescriptions(state, taxon);
381
                } catch (Exception e) {
382
                    state.getResult().addException(e,
383
                            "An unexpected problem occurred when trying to export taxon with id " + taxon.getId() + " " + taxon.getTitleCache());
384
                    state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
385
                }
386
            }
387

    
388
        } catch (Exception e) {
389
            state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
390
                    + cdmBaseStr(taxonNode.getTaxon()) + ", titleCache:"+ taxonNode.getTaxon().getTitleCache()+": " + e.getMessage());
391
        }
392
    }
393

    
394
    private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
395
        String titleCache = null;
396
        try {
397

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

    
465
    private void handleAnnotations(DescriptionElementBase element) {
466
        // TODO Auto-generated method stub
467
    }
468

    
469
    private void handleMetaData(CdmLightExportState state) {
470
        CdmLightExportTable table = CdmLightExportTable.METADATA;
471
        String[] csvLine = new String[table.getSize()];
472
//        csvLine[table.getIndex(CdmLightExportTable.INSTANCE_ID)] = state.getConfig().getInctanceId();
473
//        csvLine[table.getIndex(CdmLightExportTable.INSTANCE_NAME)] = state.getConfig().getInstanceName();
474
        csvLine[table.getIndex(CdmLightExportTable.DATASET_BASE_URL)] = state.getConfig().getBase_url();
475
        csvLine[table.getIndex(CdmLightExportTable.DATASET_CONTRIBUTOR)] = state.getConfig().getContributor();
476
        csvLine[table.getIndex(CdmLightExportTable.DATASET_CREATOR)] = state.getConfig().getCreator();
477
        csvLine[table.getIndex(CdmLightExportTable.DATASET_DESCRIPTION)] = state.getConfig().getDescription();
478
        csvLine[table.getIndex(CdmLightExportTable.DATASET_DOWNLOAD_LINK)] = state.getConfig().getDataset_download_link();
479
        csvLine[table.getIndex(CdmLightExportTable.DATASET_KEYWORDS)] = state.getConfig().getKeywords();
480
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANDINGPAGE)] = state.getConfig().getDataSet_landing_page();
481

    
482
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
483
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
484
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
485
        csvLine[table.getIndex(CdmLightExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
486
        csvLine[table.getIndex(CdmLightExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
487
        state.getProcessor().put(table, "", csvLine);
488
    }
489

    
490
    private boolean isSpecimenFeature(Feature feature) {
491
        // TODO allow user defined specimen features
492
        if (feature == null) {
493
            return false;
494
        } else if (feature.isSupportsIndividualAssociation()) {
495
            return true;
496
        } else {
497
            return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
498
                    || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
499
                    || feature.equals(Feature.OCCURRENCE());
500
        }
501
    }
502

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

    
531
    private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
532
            List<DescriptionElementBase> taxonInteractionsFacts) {
533
        CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
534
        String titleCache = null;
535
        if (cdmBase instanceof TaxonBase){
536
            titleCache = ((TaxonBase)cdmBase).getTitleCache();
537
        }
538
        for (DescriptionElementBase element : taxonInteractionsFacts) {
539

    
540
            try {
541

    
542
                String[] csvLine = new String[table.getSize()];
543

    
544
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
545
                handleSource(state, element, table);
546
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
547
                csvLine[table.getIndex(CdmLightExportTable.TAXON2_FK)] = getId(state,
548
                        ((TaxonInteraction) element).getTaxon2());
549
                csvLine[table.getIndex(CdmLightExportTable.DESCRIPTION)] = createMultilanguageString(
550
                        ((TaxonInteraction) element).getDescription());
551
                state.getProcessor().put(table, element, csvLine);
552

    
553
            } catch (Exception e) {
554
                state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
555
                        + cdmBaseStr(element) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
556
            }
557
        }
558
    }
559

    
560
    private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
561
            DescriptionElementBase element) {
562
        try {
563
            String[] csvLine;
564
            handleSource(state, element, CdmLightExportTable.MEDIA);
565

    
566
            if (element instanceof TextData) {
567
                TextData textData = (TextData) element;
568
                csvLine = new String[table.getSize()];
569
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
570
                if (cdmBase instanceof Taxon) {
571
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
572
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
573
                } else if (cdmBase instanceof TaxonName) {
574
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
575
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
576
                }
577

    
578
                String mediaUris = "";
579
                for (Media media : textData.getMedia()) {
580
                    String mediaString = extractMediaUris(media.getRepresentations().iterator());
581
                    if (!StringUtils.isBlank(mediaString)) {
582
                        mediaUris += mediaString + ";";
583
                    } else {
584
                        state.getResult().addWarning("Empty Media object for " + cdmBase.getUserFriendlyTypeName() + " "
585
                                + cdmBase.getUuid() + " (media: " + media.getUuid() + ")");
586
                    }
587
                }
588
                csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
589

    
590
            }
591
        } catch (Exception e) {
592
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
593
                    + cdmBaseStr(element) + ": " + e.getMessage());
594
        }
595

    
596
    }
597

    
598
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
599
            DescriptionElementBase element) {
600
        try {
601
            String[] csvLine;
602
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
603

    
604
            if (element instanceof TextData) {
605
                TextData textData = (TextData) element;
606
                csvLine = new String[table.getSize()];
607
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
608
                if (cdmBase instanceof Taxon) {
609
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
610
                } else if (cdmBase instanceof TaxonName) {
611
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
612
                }
613
                csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
614

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

    
650
    private String filterIntextReferences(String text) {
651
        /*
652
         * (<cdm:reference cdmId='fbd19251-efee-4ded-b780-915000f66d41'
653
         * intextId='1352d42c-e201-4155-a02a-55360d3b563e'>Ridley in Fl. Malay
654
         * Pen. 3 (1924) 22</cdm:reference>)
655
         */
656
        String newText = text.replaceAll("<cdm:reference cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
657
        newText = newText.replaceAll("</cdm:reference>", "");
658

    
659
        newText = newText.replaceAll("<cdm:key cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
660
        newText = newText.replaceAll("</cdm:key>", "");
661
        return newText;
662
    }
663

    
664
    private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon,
665
            List<DescriptionElementBase> specimenFacts) {
666
        CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
667

    
668
        for (DescriptionElementBase element : specimenFacts) {
669
            try {
670
                String[] csvLine = new String[table.getSize()];
671
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
672
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
673
                handleSource(state, element, table);
674
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(
675
                        element.getAnnotations());
676

    
677
                if (element instanceof IndividualsAssociation) {
678

    
679
                    IndividualsAssociation indAssociation = (IndividualsAssociation) element;
680
                    if (indAssociation.getAssociatedSpecimenOrObservation() == null) {
681
                        state.getResult()
682
                                .addWarning("There is an individual association with no specimen associated (Taxon "
683
                                        + taxon.getTitleCache() + "(" + taxon.getUuid() + "). Could not be exported.");
684
                        continue;
685
                    } else {
686
                        if (!state.getSpecimenStore()
687
                                .contains((indAssociation.getAssociatedSpecimenOrObservation().getUuid()))) {
688
                            SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(
689
                                    indAssociation.getAssociatedSpecimenOrObservation(),
690
                                    SpecimenOrObservationBase.class);
691

    
692
                            handleSpecimen(state, specimenBase);
693
                            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
694
                                    indAssociation.getAssociatedSpecimenOrObservation());
695
                        }
696
                    }
697
                } else if (element instanceof TextData) {
698
                    TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
699
                    csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(
700
                            textData.getMultilanguageText());
701
                }
702
                state.getProcessor().put(table, element, csvLine);
703
            } catch (Exception e) {
704
                state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact "
705
                        + cdmBaseStr(element) + ": " + e.getMessage());
706
            }
707
        }
708
    }
709

    
710
    private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
711
        String text = "";
712
        int index = multilanguageText.size();
713
        for (LanguageString langString : multilanguageText.values()) {
714
            text += langString.getText();
715
            if (index > 1) {
716
                text += "; ";
717
            }
718
            index--;
719
        }
720
        return text;
721
    }
722

    
723
    private String createAnnotationsString(Set<Annotation> annotations) {
724
        StringBuffer strBuff = new StringBuffer();
725

    
726
        for (Annotation ann : annotations) {
727
            if (ann.getAnnotationType() == null || !ann.getAnnotationType().equals(AnnotationType.TECHNICAL())) {
728
                strBuff.append(ann.getText());
729
                strBuff.append("; ");
730
            }
731
        }
732

    
733
        if (strBuff.length() > 2) {
734
            return strBuff.substring(0, strBuff.length() - 2);
735
        } else {
736
            return null;
737
        }
738
    }
739

    
740
    private void handleSource(CdmLightExportState state, DescriptionElementBase element,
741
            CdmLightExportTable factsTable) {
742
        CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
743
        try {
744
            Set<DescriptionElementSource> sources = element.getSources();
745

    
746
            for (DescriptionElementSource source : sources) {
747
                if (!(source.getType().equals(OriginalSourceType.Import)
748
                        && state.getConfig().isExcludeImportSources())) {
749
                    String[] csvLine = new String[table.getSize()];
750
                    Reference ref = source.getCitation();
751
                    if ((ref == null) && (source.getNameUsedInSource() == null)) {
752
                        continue;
753
                    }
754
                    if (ref != null) {
755
                        if (!state.getReferenceStore().contains(ref.getUuid())) {
756
                            handleReference(state, ref);
757

    
758
                        }
759
                        csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
760
                    }
761
                    csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
762

    
763
                    csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state,
764
                            source.getNameUsedInSource());
765
                    csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
766
                    if (StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])
767
                            && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])) {
768
                        continue;
769
                    }
770
                    state.getProcessor().put(table, source, csvLine);
771
                }
772

    
773
            }
774
        } catch (Exception e) {
775
            state.getResult().addException(e, "An unexpected error occurred when handling single source "
776
                    + cdmBaseStr(element) + ": " + e.getMessage());
777
        }
778

    
779
    }
780

    
781
    private void handleDistributionFacts(CdmLightExportState state, Taxon taxon,
782
            List<DescriptionElementBase> distributionFacts) {
783

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

    
817
             CondensedDistribution conDis = geoService.getCondensedDistribution(
818
                     //TODO add CondensedDistributionConfiguration to export configuration
819
                     distributions, true, null, state.getConfig().getCondensedDistributionConfiguration(), langs);
820
             CdmLightExportTable tableCondensed =
821
                     CdmLightExportTable.SIMPLE_FACT;
822
             String[] csvLine = new String[tableCondensed.getSize()];
823
             //the computed fact has no uuid, TODO: remember the uuid for later reference assignment
824
             UUID randomUuid = UUID.randomUUID();
825
             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_ID)] =
826
                     randomUuid.toString();
827
             csvLine[tableCondensed.getIndex(CdmLightExportTable.TAXON_FK)] =
828
                     getId(state, taxon);
829
             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
830
                     conDis.toString();
831
             csvLine[tableCondensed.getIndex(CdmLightExportTable.LANGUAGE)] =Language.ENGLISH().toString();
832

    
833
             csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_CATEGORY)] =
834
                     "CondensedDistribution";
835

    
836
             state.getProcessor().put(tableCondensed, taxon, csvLine);
837
         }
838
    }
839

    
840
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
841
            List<DescriptionElementBase> commonNameFacts) {
842
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
843

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

    
885
    private String getTitleCache(IIdentifiableEntity identEntity) {
886
        if (identEntity == null) {
887
            return "";
888
        }
889
        // TODO refresh?
890
        return identEntity.getTitleCache();
891
    }
892

    
893
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
894
        if (cdmBase == null) {
895
            return "";
896
        }
897
        // TODO make configurable
898
        return cdmBase.getUuid().toString();
899
    }
900

    
901
    private void handleSynonym(CdmLightExportState state, Synonym synonym, int index) {
902
        try {
903
            if (isUnpublished(state.getConfig(), synonym)) {
904
                return;
905
            }
906
            TaxonName name = synonym.getName();
907
            handleName(state, name, synonym.getAcceptedTaxon());
908

    
909
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
910
            String[] csvLine = new String[table.getSize()];
911

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

    
933
    /**
934
     * Handles misapplied names (including pro parte and partial as well as pro
935
     * parte and partial synonyms
936
     */
937
    private void handleProPartePartialMisapplied(CdmLightExportState state, Taxon taxon, Taxon accepted, boolean isProParte, boolean isMisapplied, int index) {
938
        try {
939
            Taxon ppSyonym = taxon;
940
            if (isUnpublished(state.getConfig(), ppSyonym)) {
941
                return;
942
            }
943
            TaxonName name = ppSyonym.getName();
944
            handleName(state, name, accepted);
945

    
946
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
947
            String[] csvLine = new String[table.getSize()];
948

    
949
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, ppSyonym);
950
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, accepted);
951
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
952

    
953
            Reference secRef = ppSyonym.getSec();
954

    
955
            if (secRef != null && !state.getReferenceStore().contains(secRef.getUuid())) {
956
                handleReference(state, secRef);
957
            }
958
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
959
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
960
            Set<TaxonRelationship> rels = accepted.getTaxonRelations(ppSyonym);
961
            TaxonRelationship rel = null;
962
            boolean isPartial = false;
963
            if (rels.size() == 1){
964
                rel = rels.iterator().next();
965

    
966
            }else if (rels.size() > 1){
967
                Iterator<TaxonRelationship> iterator = rels.iterator();
968
                while (iterator.hasNext()){
969
                    rel = iterator.next();
970
                    if (isProParte && rel.getType().isAnySynonym()){
971
                        break;
972
                    } else if (isMisapplied && rel.getType().isAnyMisappliedName()){
973
                        break;
974
                    }else{
975
                        rel = null;
976
                    }
977
                }
978
            }
979
            if (rel != null){
980
                Reference synSecRef = rel.getCitation();
981
                if (synSecRef != null && !state.getReferenceStore().contains(synSecRef.getUuid())) {
982
                    handleReference(state, synSecRef);
983
                }
984
                csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
985
                csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
986
                isProParte = rel.getType().isProParte();
987
                isPartial = rel.getType().isPartial();
988

    
989
            }else{
990
                state.getResult().addWarning("An unexpected error occurred when handling "
991
                        + "pro parte/partial synonym or misapplied name  " + cdmBaseStr(taxon) );
992
            }
993

    
994
            // pro parte type
995

    
996
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = isProParte ? "1" : "0";
997
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = isPartial ? "1" : "0";
998
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = isMisapplied ? "1" : "0";
999
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
1000
            state.getProcessor().put(table, ppSyonym, csvLine);
1001
        } catch (Exception e) {
1002
            state.getResult().addException(e, "An unexpected error occurred when handling "
1003
                    + "pro parte/partial synonym or misapplied name  " + cdmBaseStr(taxon) + ": " + e.getMessage());
1004
        }
1005

    
1006
    }
1007

    
1008
    private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon){
1009
        handleName(state, name, acceptedTaxon, false);
1010
    }
1011

    
1012
    private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon, boolean acceptedName) {
1013
        if (name == null || state.getNameStore().containsKey(name.getId())) {
1014
            return;
1015
        }
1016
        try {
1017
            Rank rank = name.getRank();
1018
            CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
1019
            name = HibernateProxyHelper.deproxy(name);
1020
            state.getNameStore().put(name.getId(), name.getUuid());
1021
            String[] csvLine = new String[table.getSize()];
1022

    
1023
            csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
1024
            if (name.getLsid() != null) {
1025
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
1026
            } else {
1027
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
1028
            }
1029

    
1030
            handleIdentifier(state, name);
1031
            handleDescriptions(state, name);
1032

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

    
1058

    
1059
            if (!state.getConfig().isAddHTML()) {
1060
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = name.getFullTitleCache();
1061
            } else {
1062
                List<TaggedText> taggedFullTitleCache = name.getTaggedFullTitle();
1063
                List<TaggedText> taggedName = name.getTaggedName();
1064

    
1065
                String fullTitleWithHtml = createNameWithItalics(taggedFullTitleCache);
1066
                // TODO: adapt the tropicos titlecache creation
1067
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = fullTitleWithHtml.trim();
1068
            }
1069

    
1070
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
1071
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
1072

    
1073
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
1074
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
1075

    
1076
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
1077

    
1078
            csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = name.getAppendedPhrase();
1079

    
1080
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
1081
            if (name.getBasionymAuthorship() != null) {
1082
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
1083
                    handleAuthor(state, name.getBasionymAuthorship());
1084
                }
1085
            }
1086
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state,
1087
                    name.getExBasionymAuthorship());
1088
            if (name.getExBasionymAuthorship() != null) {
1089
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
1090
                    handleAuthor(state, name.getExBasionymAuthorship());
1091
                }
1092

    
1093
            }
1094
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,
1095
                    name.getCombinationAuthorship());
1096
            if (name.getCombinationAuthorship() != null) {
1097
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
1098
                    handleAuthor(state, name.getCombinationAuthorship());
1099
                }
1100
            }
1101
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state,
1102
                    name.getExCombinationAuthorship());
1103
            if (name.getExCombinationAuthorship() != null) {
1104
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
1105
                    handleAuthor(state, name.getExCombinationAuthorship());
1106
                }
1107

    
1108
            }
1109

    
1110
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
1111

    
1112
            Reference nomRef = name.getNomenclaturalReference();
1113

    
1114
            NomenclaturalSource nomenclaturalSource = name.getNomenclaturalSource();
1115
            if (nomenclaturalSource != null &&nomenclaturalSource.getNameUsedInSource() != null){
1116
                handleName(state, nomenclaturalSource.getNameUsedInSource(), null);
1117
                csvLine[table.getIndex(CdmLightExportTable.NAME_USED_IN_SOURCE)] = getId(state, nomenclaturalSource.getNameUsedInSource());
1118
            }
1119

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

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

    
1205
                }
1206
            } else {
1207
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
1208
            }
1209

    
1210
            /*
1211
             * Collation
1212
             *
1213
             * Detail
1214
             *
1215
             * TitlePageYear
1216
             */
1217
            String protologueUriString = extractProtologueURIs(state, name);
1218

    
1219
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
1220
            Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1221
            List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1222
            for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1223
                if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1224

    
1225
                    if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1226
                        Set<IdentifiableSource> sources =  typeDesignation.getSources();
1227
                        boolean isProtologue = false;
1228
                        if (sources != null && !sources.isEmpty()){
1229
                            IdentifiableSource source = sources.iterator().next();
1230
                            if (name.getNomenclaturalReference() != null){
1231
                                isProtologue = source.getCitation() != null? source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid()): false;
1232
                            }
1233
                        }
1234
                        if (isProtologue){
1235
                            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_TYPE_STATEMENT)] = ((TextualTypeDesignation) typeDesignation)
1236
                                    .getPreferredText(Language.DEFAULT());
1237
                        }else{
1238
                            textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1239
                        }
1240

    
1241
                    } else {
1242
                        textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1243
                    }
1244
                } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1245
                    SpecimenTypeDesignation specimenType = HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class);
1246
                    specimenTypeDesignations.add(specimenType);
1247
                    handleSpecimenType(state, specimenType);
1248

    
1249

    
1250
                }else if (typeDesignation instanceof NameTypeDesignation){
1251
                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
1252
                }
1253
            }
1254
            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
1255
            HTMLTagRules rules = new HTMLTagRules();
1256
            rules.addRule(TagEnum.name, "i");
1257
            String test = manager.print(false, false, false, rules);;
1258
            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false, rules);
1259

    
1260
            StringBuilder stringbuilder = new StringBuilder();
1261
            int i = 1;
1262
            for (TextualTypeDesignation typeDesignation : textualTypeDesignations) {
1263
                stringbuilder.append(typeDesignation.getPreferredText(Language.DEFAULT()));
1264
                if (typeDesignation.getSources() != null && !typeDesignation.getSources().isEmpty() ){
1265
                    stringbuilder.append( " [");
1266
                    int index = 1;
1267
                    for (IdentifiableSource source: typeDesignation.getSources()){
1268
                        if (source.getCitation() != null){
1269
                            stringbuilder.append(OriginalSourceFormatter.INSTANCE.format(source));
1270
                        }
1271
                        if (index < typeDesignation.getSources().size()) {
1272
                            stringbuilder.append( ", ");
1273
                        }
1274
                        index++;
1275
                    }
1276
                    stringbuilder.append( "]");
1277
                }
1278
                if (i < textualTypeDesignations.size()) {
1279
                    stringbuilder.append( "; ");
1280
                } else {
1281
                    stringbuilder.append(".");
1282
                }
1283
                i++;
1284
            }
1285
            csvLine[table.getIndex(CdmLightExportTable.TYPE_STATEMENT)] = stringbuilder.toString();
1286

    
1287

    
1288
            if (name.getStatus() == null || name.getStatus().isEmpty()) {
1289
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
1290
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
1291
            } else {
1292

    
1293
                String statusStringAbbrev = extractStatusString(state, name, true);
1294
                String statusString = extractStatusString(state, name, false);
1295

    
1296
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
1297
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
1298
            }
1299

    
1300
            HomotypicalGroup group = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
1301

    
1302
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
1303
            List<TaxonName> typifiedNames = new ArrayList<>();
1304
            if (acceptedTaxon != null){
1305
                HomotypicGroupTaxonComparator comparator = new HomotypicGroupTaxonComparator(acceptedTaxon);
1306
                List<Synonym> synonymsInGroup = null;
1307
                if (group.equals(acceptedTaxon.getHomotypicGroup())){
1308
                    synonymsInGroup = acceptedTaxon.getHomotypicSynonymsByHomotypicGroup(comparator);
1309
                    typifiedNames.add(name);
1310
                }else{
1311
                    synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group, comparator);
1312
                }
1313

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

    
1316
            }else{
1317
                typifiedNames.addAll(group.getTypifiedNames());
1318
            }
1319

    
1320

    
1321
            Integer seqNumber = typifiedNames.indexOf(name);
1322
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1323
            state.getProcessor().put(table, name, csvLine);
1324
            handleNameRelationships(state, name);
1325

    
1326
        } catch (Exception e) {
1327
            state.getResult().addException(e,
1328
                    "An unexpected error occurred when handling the name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1329

    
1330
            e.printStackTrace();
1331
        }
1332
    }
1333

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

    
1373
            state.getProcessor().put(table, specimenType, csvLine);
1374
        }
1375
    }
1376

    
1377

    
1378
    /**
1379
     * @param specimenType
1380
     */
1381
    private void handleSpecimenType(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1382
        if (specimenType.getTypeSpecimen() != null){
1383
            DerivedUnit specimen =  specimenType.getTypeSpecimen();
1384
            if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1385
               handleSpecimen(state, specimen);
1386
            }
1387
        }
1388
        CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1389
        String[] csvLine = new String[table.getSize()];
1390

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

    
1440
            csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1441
            if (sources.get(0).getCitation() != null ){
1442
                csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_FK)] = getId(state, sources.get(0).getCitation());
1443
            }
1444
        }
1445
        if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1446
            handleReference(state, specimenType.getDesignationSource().getCitation());
1447
            csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1448
        }
1449

    
1450

    
1451
        Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1452

    
1453
        if (typifiedNames.size() > 1){
1454
            state.getResult().addWarning("Please check the specimen type  "
1455
                    + cdmBaseStr(specimenType) + " there are more then one typified name.");
1456
        }
1457
        if (typifiedNames.iterator().hasNext()){
1458
            TaxonName name = typifiedNames.iterator().next();
1459
            csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1460
        }
1461
        state.getProcessor().put(table, specimenType, csvLine);
1462

    
1463

    
1464

    
1465

    
1466

    
1467
    }
1468

    
1469

    
1470
    private String createNameWithItalics(List<TaggedText> taggedName) {
1471

    
1472
        String fullTitleWithHtml = "";
1473
        for (TaggedText taggedText: taggedName){
1474
            if (taggedText.getType().equals(TagEnum.name)){
1475
                fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1476
            }else if (taggedText.getType().equals(TagEnum.separator)){
1477
                fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1478
            }else{
1479
                fullTitleWithHtml += taggedText.getText() + " ";
1480
            }
1481
        }
1482
        return fullTitleWithHtml;
1483
    }
1484

    
1485
    private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1486
        Set<NameRelationship> rels = name.getRelationsFromThisName();
1487
        CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1488
        String[] csvLine = new String[table.getSize()];
1489

    
1490
        for (NameRelationship rel : rels) {
1491
            NameRelationshipType type = rel.getType();
1492
            TaxonName name2 = rel.getToName();
1493
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1494
            if (!state.getNameStore().containsKey(name2.getId())) {
1495
                handleName(state, name2, null);
1496
            }
1497

    
1498
            csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1499
            csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1500
            csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1501
            state.getProcessor().put(table, name, csvLine);
1502
        }
1503

    
1504
        rels = name.getRelationsToThisName();
1505

    
1506
        csvLine = new String[table.getSize()];
1507

    
1508
        for (NameRelationship rel : rels) {
1509
            NameRelationshipType type = rel.getType();
1510
            TaxonName name2 = rel.getFromName();
1511
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1512
            if (!state.getNameStore().containsKey(name2.getId())) {
1513
                handleName(state, name2, null);
1514
            }
1515

    
1516

    
1517
        }
1518
    }
1519

    
1520
    private String createCollatation(TaxonName name) {
1521
        String collation = "";
1522
        if (name.getNomenclaturalReference() != null) {
1523
            Reference ref = name.getNomenclaturalReference();
1524
            collation = getVolume(ref);
1525
        }
1526
        if (name.getNomenclaturalMicroReference() != null) {
1527
            if (!StringUtils.isBlank(collation)) {
1528
                collation += ":";
1529
            }
1530
            collation += name.getNomenclaturalMicroReference();
1531
        }
1532

    
1533
        return collation;
1534
    }
1535

    
1536
    private String getVolume(Reference reference) {
1537
        if (reference.getVolume() != null) {
1538
            return reference.getVolume();
1539
        } else if (reference.getInReference() != null) {
1540
            if (reference.getInReference().getVolume() != null) {
1541
                return reference.getInReference().getVolume();
1542
            }
1543
        }
1544
        return null;
1545
    }
1546

    
1547
    private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1548
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1549
        String[] csvLine;
1550
        try {
1551
            if (cdmBase instanceof TaxonName){
1552
                TaxonName name = (TaxonName)cdmBase;
1553

    
1554
                try{
1555
                    List<Identifier> identifiers = name.getIdentifiers();
1556

    
1557
                    //first check which kind of identifiers are available and then sort and create table entries
1558
                    Map<DefinedTerm, Set<Identifier>> identifierTypes = new HashMap<>();
1559
                    for (Identifier identifier: identifiers){
1560
                        DefinedTerm type = identifier.getType();
1561
                        if (identifierTypes.containsKey(type)){
1562
                            identifierTypes.get(type).add(identifier);
1563
                        }else{
1564
                            Set<Identifier> tempList = new HashSet<>();
1565
                            tempList.add(identifier);
1566
                            identifierTypes.put(type, tempList);
1567
                        }
1568
                    }
1569

    
1570
                    for (DefinedTerm type:identifierTypes.keySet()){
1571
                        Set<Identifier> identifiersByType = identifierTypes.get(type);
1572
                        csvLine = new String[table.getSize()];
1573
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1574
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1575
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = type.getLabel();
1576
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1577
                                identifiersByType);
1578
                        state.getProcessor().put(table, name.getUuid() + ", " + type.getLabel(), csvLine);
1579
                    }
1580

    
1581

    
1582
//                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1583
//                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1584
//                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1585
//                    if (!IPNIidentifiers.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)] = IPNI_NAME_IDENTIFIER;
1590
//                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1591
//                                IPNIidentifiers);
1592
//                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1593
//                    }
1594
//                    if (!tropicosIdentifiers.isEmpty()) {
1595
//                        csvLine = new String[table.getSize()];
1596
//                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1597
//                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1598
//                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
1599
//                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1600
//                                tropicosIdentifiers);
1601
//                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1602
//                    }
1603
//                    if (!WFOIdentifiers.isEmpty()) {
1604
//                        csvLine = new String[table.getSize()];
1605
//                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1606
//                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1607
//                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1608
//                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1609
//                                WFOIdentifiers);
1610
//                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1611
//                    }
1612
                }catch(Exception e){
1613
                    state.getResult().addWarning("Please check the identifiers for "
1614
                            + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1615

    
1616

    
1617
                }
1618
            }else{
1619
                if (cdmBase instanceof IdentifiableEntity){
1620
                    IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1621
                    List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1622
                    String tableName = null;
1623
                    if (cdmBase instanceof Reference){
1624
                        tableName = "Reference";
1625
                    }else if (cdmBase instanceof SpecimenOrObservationBase){
1626
                        tableName = "Specimen";
1627
                    }else if (cdmBase instanceof Taxon){
1628
                        tableName = "Taxon";
1629
                    }else if (cdmBase instanceof Synonym){
1630
                        tableName = "Synonym";
1631
                    }else if (cdmBase instanceof TeamOrPersonBase){
1632
                        tableName = "PersonOrTeam";
1633
                    }
1634

    
1635
                    for (Identifier identifier: identifiers){
1636
                        if (identifier.getType() == null && identifier.getIdentifier() == null){
1637
                            state.getResult().addWarning("Please check the identifiers for "
1638
                                    + cdmBaseStr(cdmBase) + " there is an empty identifier");
1639
                            continue;
1640
                        }
1641

    
1642
                        csvLine = new String[table.getSize()];
1643
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1644

    
1645
                        if (tableName != null){
1646
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1647
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1648
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1649
                            state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1650
                        }
1651
                    }
1652
                    if (cdmBase instanceof Reference ){
1653
                        Reference ref = (Reference)cdmBase;
1654
                        if (ref.getDoi() != null){
1655
                            csvLine = new String[table.getSize()];
1656
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1657
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1658
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1659
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1660
                            state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1661
                        }
1662
                    }
1663

    
1664
                    if (cdmBase instanceof TeamOrPersonBase){
1665
                        TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1666
                        if (person instanceof Person &&  ((Person)person).getOrcid() != null){
1667
                            csvLine = new String[table.getSize()];
1668
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1669
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1670
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1671
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]=  ((Person)person).getOrcid().asURI();
1672
                            state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1673
                        }
1674
                    }
1675
                }
1676
            }
1677
        } catch (Exception e) {
1678
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1679
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1680
            e.printStackTrace();
1681
        }
1682
    }
1683

    
1684
    private String extractIdentifier(Set<Identifier> identifierSet) {
1685

    
1686
        String identifierString = "";
1687
        for (Identifier identifier : identifierSet) {
1688
            if (!StringUtils.isBlank(identifierString)) {
1689
                identifierString += ", ";
1690
            }
1691
            identifierString += identifier.getIdentifier();
1692
        }
1693
        return identifierString;
1694
    }
1695

    
1696
    private String extractProtologueURIs(CdmLightExportState state, TaxonName name) {
1697
        if (name.getNomenclaturalSource() != null){
1698
            Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1699
            return extractLinkUris(links.iterator());
1700
        }else{
1701
            return null;
1702
        }
1703
    }
1704

    
1705
    private String extractMediaURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1706
            Feature feature) {
1707

    
1708
        String mediaUriString = "";
1709
        Set<DescriptionElementBase> elements = new HashSet<>();
1710
        for (DescriptionBase<?> description : descriptionsSet) {
1711
            try {
1712
                if (!description.getElements().isEmpty()) {
1713
                    elements = description.getElements();
1714

    
1715
                    for (DescriptionElementBase element : elements) {
1716
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1717
                        if (entityFeature.equals(feature)) {
1718
                            if (!element.getMedia().isEmpty()) {
1719
                                List<Media> media = element.getMedia();
1720
                                for (Media mediaElement : media) {
1721
                                    Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1722
                                    mediaUriString = extractMediaUris(it);
1723
                                }
1724
                            }
1725
                        }
1726
                    }
1727
                }
1728
            } catch (Exception e) {
1729
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1730
                        + cdmBaseStr(description) + ": " + e.getMessage());
1731
            }
1732
        }
1733
        return mediaUriString;
1734
    }
1735

    
1736
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1737
        try {
1738
            if (state.getAuthorFromStore(author.getId()) != null) {
1739
                return;
1740
            }
1741
            state.addAuthorToStore(author);
1742
            handleIdentifier(state, author);
1743
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1744
            String[] csvLine = new String[table.getSize()];
1745
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1746
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
1747
            String[] csvLineMember = new String[table.getSize()];
1748
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1749
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1750
                    ? author.getTitleCache() : author.getNomenclaturalTitleCache();
1751
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1752
            author = HibernateProxyHelper.deproxy(author);
1753
            if (author instanceof Person) {
1754
                Person authorPerson = (Person) author;
1755
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1756
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1757
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1758
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1759
            } else {
1760
                // create an entry in rel table and all members in author table,
1761
                // check whether the team members already in author table
1762

    
1763
                Team authorTeam = (Team) author;
1764
                int index = 0;
1765
                for (Person member : authorTeam.getTeamMembers()) {
1766
                    csvLineRel = new String[tableAuthorRel.getSize()];
1767
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1768
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1769
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1770
                            .valueOf(index);
1771
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1772

    
1773
                    if (state.getAuthorFromStore(member.getId()) == null) {
1774
                        state.addAuthorToStore(member);
1775
                        csvLineMember = new String[table.getSize()];
1776
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1777
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1778
                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitleCache();
1779
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1780
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1781
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1782
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1783
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1784
                        state.getProcessor().put(table, member, csvLineMember);
1785
                    }
1786
                    index++;
1787
                }
1788
            }
1789
            state.getProcessor().put(table, author, csvLine);
1790
        } catch (Exception e) {
1791
            state.getResult().addException(e,
1792
                    "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1793
        }
1794
    }
1795

    
1796
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1797
        try {
1798
            Set<NomenclaturalStatus> status = name.getStatus();
1799
            if (status.isEmpty()) {
1800
                return "";
1801
            }
1802
            String statusString = "";
1803
            for (NomenclaturalStatus nameStatus : status) {
1804
                if (nameStatus != null) {
1805
                    if (abbrev) {
1806
                        if (nameStatus.getType() != null) {
1807
                            statusString += nameStatus.getType().getIdInVocabulary();
1808
                        }
1809
                    } else {
1810
                        if (nameStatus.getType() != null) {
1811
                            statusString += nameStatus.getType().getTitleCache();
1812
                        }
1813
                    }
1814
                    if (!abbrev) {
1815

    
1816
                        if (nameStatus.getRuleConsidered() != null
1817
                                && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1818
                            statusString += ": " + nameStatus.getRuleConsidered();
1819
                        }
1820
                        if (nameStatus.getCitation() != null) {
1821
                            String shortCitation = OriginalSourceFormatter.INSTANCE.format(nameStatus.getCitation(), null);
1822
                            statusString += " (" + shortCitation + ")";
1823
                        }
1824
//                        if (nameStatus.getCitationMicroReference() != null
1825
//                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1826
//                            statusString += " " + nameStatus.getCitationMicroReference();
1827
//                        }
1828
                    }
1829
                    statusString += " ";
1830
                }
1831
            }
1832
            return statusString;
1833
        } catch (Exception e) {
1834
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1835
                    + cdmBaseStr(name) + ": " + e.getMessage());
1836
            return "";
1837
        }
1838
    }
1839

    
1840
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, Taxon acceptedTaxon, int sortIndex) {
1841
        try {
1842
            state.addHomotypicalGroupToStore(group);
1843
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1844
            String[] csvLine = new String[table.getSize()];
1845
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(sortIndex);
1846
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1847

    
1848
            List<TaxonName> typifiedNames = new ArrayList<>();
1849
            if (acceptedTaxon != null){
1850
                List<Synonym> synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group);
1851
                if (group.equals(acceptedTaxon.getHomotypicGroup())){
1852
                    typifiedNames.add(acceptedTaxon.getName());
1853
                }
1854
                synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(CdmBase.deproxy(synonym.getName())));
1855
            }
1856

    
1857

    
1858
            TaxonName firstname = null;
1859
            for (TaxonName name: typifiedNames){
1860
                Iterator<Taxon> taxa = name.getTaxa().iterator();
1861
                while(taxa.hasNext()){
1862
                    Taxon taxon = taxa.next();
1863
                    if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1864
                        firstname = name;
1865
                        break;
1866
                    }
1867
                }
1868
            }
1869

    
1870
//            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1871
            String typifiedNamesString = "";
1872
            String typifiedNamesWithSecString = "";
1873
            String typifiedNamesWithoutAccepted = "";
1874
            String typifiedNamesWithoutAcceptedWithSec = "";
1875
            int index = 0;
1876
            for (TaxonName name : typifiedNames) {
1877
                // Concatenated output string for homotypic group (names and
1878
                // citations) + status + some name relations (e.g. “non”)
1879
                // TODO: nameRelations, which and how to display
1880
                Set<TaxonBase> taxonBases = name.getTaxonBases();
1881
                TaxonBase<?> taxonBase;
1882

    
1883
                String sec = "";
1884
                String nameString = name.getFullTitleCache();
1885
                String doubtful = "";
1886

    
1887
                if (state.getConfig().isAddHTML()){
1888
                    nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1889
                }
1890

    
1891
                Set<NameRelationship> related = name.getNameRelations();
1892
                List<NameRelationship> relatedList = new ArrayList<>(related);
1893

    
1894
                Collections.sort(relatedList, new Comparator<NameRelationship>() {
1895
                    @Override
1896
                    public int compare(NameRelationship nr1, NameRelationship nr2) {
1897
                        return nr1.getType().compareTo(nr2.getType());
1898
                    }
1899

    
1900
                });
1901

    
1902
                List<NameRelationship> nonNames = new ArrayList<>();
1903
                List<NameRelationship> otherRelationships = new ArrayList<>();
1904

    
1905
                for (NameRelationship rel: relatedList){
1906
                    //no inverse relations
1907
                    if (rel.getFromName().equals(name)){
1908
                     // alle Homonyme und inverse blocking names
1909
                        if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1910
                                || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1911
                                || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1912
                                || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))){
1913
                            nonNames.add(rel);
1914
                        }else if (!rel.getType().isBasionymRelation()){
1915
                            otherRelationships.add(rel);
1916
                        }
1917
                    }
1918
                }
1919

    
1920
                String nonRelNames = "";
1921
                String relNames = "";
1922

    
1923
                if (nonNames.size() > 0){
1924
                    nonRelNames += " [";
1925
                }
1926
                for (NameRelationship relName: nonNames){
1927
                    String label = "non ";
1928
                    TaxonName relatedName = null;
1929
                    if (relName.getFromName().equals(name)){
1930
                        relatedName = relName.getToName();
1931
                        nonRelNames += label + relatedName.getTitleCache() + " ";
1932
                    }
1933
//                    else{
1934
//                        label = relName.getType().getInverseLabel() + " ";
1935
//                        relatedName = relName.getFromName();
1936
//                        nonRelNames += label + relatedName.getTitleCache() + " ";
1937
//                    }
1938

    
1939

    
1940
                }
1941
                relNames.trim();
1942
                if (nonNames.size() > 0){
1943
                    nonRelNames = StringUtils.strip(nonRelNames, null);
1944
                    nonRelNames += "] ";
1945
                }
1946

    
1947
                if (otherRelationships.size() > 0){
1948
                    relNames += " [";
1949
                }
1950
                for (NameRelationship rel: otherRelationships){
1951
                    String label = "";
1952
                    TaxonName relatedName = null;
1953
                    if (rel.getFromName().equals(name)){
1954
                        label = rel.getType().getLabel() + " ";
1955
                        relatedName = rel.getToName();
1956
                        if (state.getConfig().isAddHTML()){
1957
                            relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
1958
                        }else{
1959
                            relNames += label + relatedName.getTitleCache();
1960
                        }
1961
                    }
1962
//                    else {
1963
//                        label = rel.getType().getInverseLabel() + " ";
1964
//                        relatedName = rel.getFromName();
1965
//                    }
1966

    
1967
                }
1968
                relNames.trim();
1969
                if (otherRelationships.size() > 0){
1970
                    relNames = StringUtils.stripEnd(relNames, null);
1971
                    relNames += "] ";
1972
                }
1973

    
1974
                String synonymSign = "";
1975
                if (index > 0){
1976
                    if (name.isInvalid()){
1977
                        synonymSign = "\u2212 ";
1978
                    }else{
1979
                        synonymSign = "\u2261 ";
1980
                    }
1981
                }else{
1982
                    if (name.isInvalid() ){
1983
                        synonymSign = "\u2212 ";
1984
                    }else{
1985
                        synonymSign = "\u003D ";
1986
                    }
1987
                }
1988
                boolean isAccepted = false;
1989

    
1990
                if (taxonBases.size() == 1){
1991
                     taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
1992

    
1993
                     if (taxonBase.getSec() != null){
1994
                         sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(taxonBase.getSecSource());
1995
                     }
1996
                     if (taxonBase.isDoubtful()){
1997
                         doubtful = "?";
1998
                     }else{
1999
                         doubtful = "";
2000
                     }
2001
                     if (taxonBase instanceof Synonym){
2002
                         if (isNotBlank(sec)){
2003
                             sec = " syn. sec. " + sec + " ";
2004
                         }else {
2005
                             sec = "";
2006
                         }
2007

    
2008
                         typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + nonRelNames + relNames;
2009
                         typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2010
                     }else{
2011
//                         sec = "";
2012
                         if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
2013
                             isAccepted = true;
2014
                         }else {
2015
                             synonymSign = "\u003D ";
2016
                         }
2017

    
2018
                     }
2019
                     if (taxonBase.getAppendedPhrase() != null){
2020
                         if (state.getConfig().isAddHTML()){
2021
                             String taxonString = createNameWithItalics(taxonBase.getTaggedTitle()) ;
2022
                             taxonString = taxonString.replace("sec "+sec, "");
2023
                             String nameCacheWithItalics = createNameWithItalics(name.getTaggedName());
2024
                             nameString = nameString.replace(nameCacheWithItalics, taxonString);
2025
                         }
2026
                     }
2027
                }else{
2028
                    //there are names used more than once?
2029
                    for (TaxonBase<?> tb: taxonBases){
2030
                        if (tb.getSec() != null){
2031
                            sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(tb.getSecSource());
2032
                        }
2033
                        if (tb.isDoubtful()){
2034
                            doubtful = "?";
2035
                        }else{
2036
                            doubtful = "";
2037
                        }
2038
                        if (tb instanceof Synonym){
2039
                            if (StringUtils.isNotBlank(sec)){
2040
                                sec = " syn. sec. " + sec + " ";
2041
                            }else {
2042
                                sec = "";
2043
                            }
2044

    
2045
                            break;
2046
                        }else{
2047
                            sec = "";
2048
                            if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
2049
                                isAccepted = true;
2050
                                break;
2051
                            }else {
2052
                                synonymSign = "\u003D ";
2053
                            }
2054

    
2055
                        }
2056
                    }
2057
                    if (!isAccepted){
2058
                        typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + "; ";
2059
                        typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec;
2060
                        typifiedNamesWithoutAcceptedWithSec = typifiedNamesWithoutAcceptedWithSec.trim() + "; ";
2061
                    }
2062
                }
2063
                typifiedNamesString += synonymSign + doubtful + nameString + nonRelNames + relNames;
2064
                typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2065

    
2066

    
2067
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
2068

    
2069
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
2070

    
2071
                if (typifiedNamesWithoutAccepted != null && firstname != null) {
2072
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
2073
                } else {
2074
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = "";
2075
                }
2076

    
2077
                if (typifiedNamesWithoutAcceptedWithSec != null && firstname != null) {
2078
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = typifiedNamesWithoutAcceptedWithSec.trim();
2079
                } else {
2080
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = "";
2081
                }
2082
                index++;
2083
            }
2084

    
2085
            Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
2086
            List<TypeDesignationBase<?>> designationList = new ArrayList<>();
2087
            designationList.addAll(typeDesigantionSet);
2088
            Collections.sort(designationList, new TypeComparator());
2089

    
2090
            List<TaggedText> list = new ArrayList<>();
2091
            if (!designationList.isEmpty()) {
2092
                TypeDesignationSetManager manager = new TypeDesignationSetManager(group);
2093
                list.addAll(new TypeDesignationSetFormatter(true, false, false).toTaggedText(manager));
2094
            }
2095
            String typeTextDesignations = "";
2096
            //The typeDesignationManager does not handle the textual typeDesignations
2097
            for (TypeDesignationBase<?> typeDes: designationList) {
2098
            	if (typeDes instanceof TextualTypeDesignation) {
2099
            		typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
2100
            		String typeDesStateRefs = "";
2101
                    if (typeDes.getDesignationSource() != null ){
2102
                        typeDesStateRefs = "[";
2103
                        NamedSource source = typeDes.getDesignationSource();
2104
                        if (source.getCitation() != null){
2105
                            typeDesStateRefs += "fide " + OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2106
                        }
2107
                        typeDesStateRefs += "]";
2108
                    }else if (typeDes.getSources() != null && !typeDes.getSources().isEmpty()){
2109
                        typeDesStateRefs = "[";
2110
                        for (IdentifiableSource source: typeDes.getSources()) {
2111
                            if (source.getCitation() != null){
2112
                                typeDesStateRefs += "fide " +OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2113
                            }
2114
                        }
2115

    
2116
                        typeDesStateRefs += "]";
2117
                    }
2118

    
2119
            		typeTextDesignations =  typeTextDesignations + typeDesStateRefs +"; ";
2120

    
2121
            	}else if (typeDes instanceof SpecimenTypeDesignation){
2122
            	    DerivedUnit specimen =  ((SpecimenTypeDesignation)typeDes).getTypeSpecimen();
2123
            	    if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
2124
            	        handleSpecimen(state, specimen);
2125
            	    }
2126
            	}
2127
            }
2128
            if (typeTextDesignations.equals("; ")) {
2129
            	typeTextDesignations = "";
2130
            }
2131
            if (StringUtils.isNotBlank(typeTextDesignations)) {
2132
            	typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
2133
            }
2134
            String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
2135

    
2136
            if (StringUtils.isNotBlank(specimenTypeString)) {
2137
                if (!specimenTypeString.endsWith(".")) {
2138
                	specimenTypeString = specimenTypeString + ".";
2139
                }
2140
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
2141

    
2142
            } else {
2143
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
2144
            }
2145
            if (StringUtils.isNotBlank(typeTextDesignations)) {
2146
                if (!typeTextDesignations.endsWith(".")) {
2147
                	typeTextDesignations = typeTextDesignations + ".";
2148
                }
2149
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
2150

    
2151
            } else {
2152
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
2153
            }
2154
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
2155
        } catch (Exception e) {
2156
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
2157
                    + cdmBaseStr(group) + ": " + e.getMessage());
2158
        }
2159
    }
2160

    
2161
    private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup, boolean isSpecimenTypeDesignation) {
2162
        StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
2163

    
2164
        for (TaggedText text : list) {
2165
            if (text == null || text.getText() == null){
2166
                continue;  //just in case
2167
            }
2168
            if ((text.getText().equalsIgnoreCase("Type:")  //should not happen anymore
2169
                    || text.getText().equalsIgnoreCase("Nametype:")  //should not happen anymore
2170
                    || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
2171
                // do nothing
2172
            }else if (text.getType().equals(TagEnum.reference)) {
2173
                homotypicalGroupTypeDesignationString.append(text.getText());
2174
            }else if (text.getType().equals(TagEnum.name)){
2175
                if (!isSpecimenTypeDesignation){
2176
                    homotypicalGroupTypeDesignationString
2177
                        .append("<i>"+text.getText()+"</i> ");
2178
                }
2179
            }else if (text.getType().equals(TagEnum.typeDesignation) ) {
2180
                if(isSpecimenTypeDesignation){
2181
                    homotypicalGroupTypeDesignationString
2182
                        .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
2183
                }else{
2184
                    homotypicalGroupTypeDesignationString
2185
                        .append(text.getText());
2186
                }
2187

    
2188
            } else {
2189
                homotypicalGroupTypeDesignationString.append(text.getText());
2190
            }
2191
        }
2192

    
2193
        String typeDesignations = homotypicalGroupTypeDesignationString.toString();
2194
        typeDesignations = typeDesignations.trim();
2195

    
2196
        if (typeDesignations.endsWith(";")){
2197
            typeDesignations = typeDesignations.substring(0, typeDesignations.length()-1);
2198
        }
2199
        typeDesignations += ".";
2200
        typeDesignations = typeDesignations.replace("..", ".");
2201
        typeDesignations = typeDesignations.replace(". .", ".");
2202
        typeDesignations = typeDesignations.replace("; \u2261", " \u2261 ");
2203

    
2204
        if (typeDesignations.trim().equals(".")) {
2205
            typeDesignations = null;
2206
        }
2207

    
2208
        return typeDesignations;
2209
    }
2210

    
2211
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
2212
        try {
2213
            String basionymStart = "(";
2214
            String basionymEnd = ") ";
2215
            String exAuthorSeperator = " ex ";
2216
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
2217
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
2218
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
2219
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
2220

    
2221
            String combinationAuthorString = "";
2222
            if (combinationAuthor != null) {
2223
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
2224
                if (combinationAuthor instanceof Team) {
2225
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
2226
                } else {
2227
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
2228
                    combinationAuthorString = createTropicosAuthorString(person);
2229
                }
2230
            }
2231
            String exCombinationAuthorString = "";
2232
            if (exCombinationAuthor != null) {
2233
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
2234
                if (exCombinationAuthor instanceof Team) {
2235
                    exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
2236
                } else {
2237
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
2238
                    exCombinationAuthorString = createTropicosAuthorString(person);
2239
                }
2240
            }
2241

    
2242
            String basionymAuthorString = "";
2243
            if (basionymAuthor != null) {
2244
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
2245
                if (basionymAuthor instanceof Team) {
2246
                    basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
2247
                } else {
2248
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
2249
                    basionymAuthorString = createTropicosAuthorString(person);
2250
                }
2251
            }
2252

    
2253
            String exBasionymAuthorString = "";
2254

    
2255
            if (exBasionymAuthor != null) {
2256
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
2257
                if (exBasionymAuthor instanceof Team) {
2258
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
2259

    
2260
                } else {
2261
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
2262
                    exBasionymAuthorString = createTropicosAuthorString(person);
2263
                }
2264
            }
2265
            String completeAuthorString = name.getNameCache() + " ";
2266

    
2267
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2268
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
2269
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
2270
                    ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
2271
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
2272
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2273
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
2274
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
2275
                    ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
2276
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
2277
                    : "";
2278

    
2279
            return completeAuthorString;
2280
        } catch (Exception e) {
2281
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
2282
                    + cdmBaseStr(name) + ": " + e.getMessage());
2283
            return null;
2284
        }
2285
    }
2286

    
2287
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
2288
        String combinationAuthorString;
2289
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
2290
        Team tempTeam = Team.NewInstance();
2291
        for (Person teamMember : team.getTeamMembers()) {
2292
            combinationAuthorString = createTropicosAuthorString(teamMember);
2293
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
2294
            tempTeam.addTeamMember(tempPerson);
2295
        }
2296
        combinationAuthorString = tempTeam.generateTitle();
2297
        return combinationAuthorString;
2298
    }
2299

    
2300
    private String createTropicosAuthorString(Person teamMember) {
2301
        String nomAuthorString = "";
2302
        String[] splittedAuthorString = null;
2303
        if (teamMember == null) {
2304
            return nomAuthorString;
2305
        }
2306

    
2307
        if (teamMember.getGivenName() != null) {
2308
            String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
2309
            splittedAuthorString = givenNameString.split("\\s");
2310
            for (String split : splittedAuthorString) {
2311
                if (!StringUtils.isBlank(split)) {
2312
                    nomAuthorString += split.substring(0, 1);
2313
                    nomAuthorString += ".";
2314
                }
2315
            }
2316
        }
2317
        if (teamMember.getFamilyName() != null) {
2318
            String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
2319
            splittedAuthorString = familyNameString.split("\\s");
2320
            for (String split : splittedAuthorString) {
2321
                nomAuthorString += " " + split;
2322
            }
2323
        }
2324
        if (isBlank(nomAuthorString.trim())) {
2325
            if (teamMember.getTitleCache() != null) {
2326
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
2327
                splittedAuthorString = titleCacheString.split("\\s");
2328
            } else {
2329
                splittedAuthorString = new String[0];
2330
            }
2331

    
2332
            int index = 0;
2333
            for (String split : splittedAuthorString) {
2334
                if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
2335
                    nomAuthorString += split;
2336
                } else {
2337
                    nomAuthorString = nomAuthorString + " " + split;
2338
                }
2339
                index++;
2340
            }
2341
        }
2342
        return nomAuthorString.trim();
2343
    }
2344

    
2345
    private void handleReference(CdmLightExportState state, Reference reference) {
2346
        try {
2347
            state.addReferenceToStore(reference);
2348
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
2349
            reference = HibernateProxyHelper.deproxy(reference);
2350

    
2351
            handleIdentifier(state, reference);
2352
            String[] csvLine = new String[table.getSize()];
2353
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
2354
            // TODO short citations correctly
2355
            String shortCitation = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(reference, null); // Should be Author(year) like in Taxon.sec
2356
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
2357
            // TODO get preferred title
2358
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
2359
                    ? reference.getTitleCache() : reference.getTitle();
2360
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
2361
                    ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
2362
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
2363
            // TBC
2364
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
2365
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
2366
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
2367
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
2368
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
2369
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
2370
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
2371
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
2372
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
2373
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
2374
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
2375
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
2376

    
2377
            if (reference.getAuthorship() != null) {
2378
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
2379
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
2380
            }
2381

    
2382
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
2383
            if (reference.getInReference() != null
2384
                    && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
2385
                handleReference(state, reference.getInReference());
2386
            }
2387
            if (reference.getInstitution() != null) {
2388
                csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
2389
            }
2390
            if (reference.getLsid() != null) {
2391
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
2392
            }
2393
            if (reference.getSchool() != null) {
2394
                csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
2395
            }
2396
            if (reference.getUri() != null) {
2397
                csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
2398
            }
2399
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
2400

    
2401
            state.getProcessor().put(table, reference, csvLine);
2402
        } catch (Exception e) {
2403
            state.getResult().addException(e, "An unexpected error occurred when handling reference "
2404
                    + cdmBaseStr(reference) + ": " + e.getMessage());
2405
        }
2406
    }
2407

    
2408
    private String createFullAuthorship(Reference reference) {
2409
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
2410
        String fullAuthorship = "";
2411
        if (authorship == null) {
2412
            return null;
2413
        }
2414
        authorship = HibernateProxyHelper.deproxy(authorship);
2415
        if (authorship instanceof Person) {
2416
            fullAuthorship = ((Person) authorship).getTitleCache();
2417

    
2418
        } else if (authorship instanceof Team) {
2419

    
2420
            Team authorTeam = (Team)authorship;
2421
            fullAuthorship = authorTeam.cacheStrategy().getTitleCache(authorTeam);
2422
        }
2423
        return fullAuthorship;
2424
    }
2425

    
2426
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
2427
        try {
2428
            state.addSpecimenToStore(specimen);
2429
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
2430
            String specimenId = getId(state, specimen);
2431
            String[] csvLine = new String[table.getSize()];
2432

    
2433
            /*
2434
             * SpecimenCitation = “El Salvador, Municipio La Libertad, San
2435
             * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
2436
             * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
2437
             * HerbariumCode
2438
             *
2439
             */
2440

    
2441
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
2442
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
2443
            Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
2444
            if (fieldUnits.size() == 1) {
2445
                Iterator<FieldUnit> iterator = fieldUnits.iterator();
2446
                if (iterator.hasNext()){
2447
                    FieldUnit fieldUnit = iterator.next();
2448
                    csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
2449
                }
2450
            }
2451
            if (specimen.isInstanceOf(DerivedUnit.class)){
2452
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
2453
                if (!StringUtils.isBlank(derivedUnit.getBarcode())){
2454
                    csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
2455
                }
2456
                if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
2457
                    csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
2458
                }
2459
                if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
2460
                    csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
2461
                }
2462
            }
2463

    
2464
            csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
2465
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
2466
                    specimen.getDescriptions(), Feature.IMAGE());
2467
            if (specimen instanceof DerivedUnit) {
2468
                DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(specimen, DerivedUnit.class);
2469
                if (derivedUnit.getCollection() != null) {
2470
                    csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
2471
                            .getCode();
2472
                }
2473

    
2474
                if (specimen instanceof MediaSpecimen) {
2475
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
2476
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
2477
                    String mediaUris = extractMediaUris(it);
2478
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
2479

    
2480
                }
2481

    
2482
                if (derivedUnit.getDerivedFrom() != null) {
2483
                    for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
2484
                        // TODO: What to do if there are more then one
2485
                        // FieldUnit??
2486
                        if (original instanceof FieldUnit) {
2487
                            FieldUnit fieldUnit = (FieldUnit) original;
2488
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
2489

    
2490
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
2491
                            if (gathering != null) {
2492
                                if (gathering.getLocality() != null) {
2493
                                    csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
2494
                                            .getText();
2495
                                }
2496
                                if (gathering.getCountry() != null) {
2497
                                    csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
2498
                                            .getLabel();
2499
                                }
2500
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2501
                                        state, gathering, fieldUnit);
2502

    
2503
                                if (gathering.getGatheringDate() != null) {
2504
                                    csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2505
                                            .getGatheringDate().toString();
2506
                                }
2507
                                if (!gathering.getCollectingAreas().isEmpty()) {
2508
                                    int index = 0;
2509
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2510
                                    for (NamedArea area : gathering.getCollectingAreas()) {
2511
                                        if (index == 0) {
2512
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2513
                                                    .getLevel().getLabel():"";
2514
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2515
                                        }
2516
                                        if (index == 1) {
2517
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2518
                                                    .getLevel().getLabel():"";
2519
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2520
                                        }
2521
                                        if (index == 2) {
2522
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2523
                                                    .getLevel().getLabel():"";
2524
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2525
                                        }
2526
                                        if (index == 3) {
2527
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2528
                                            break;
2529
                                        }
2530
                                        index++;
2531
                                    }
2532
                                }
2533
                            }
2534
                        }
2535
                    }
2536
                } else {
2537
                    state.getResult().addWarning("The specimen with uuid " + specimen.getUuid()
2538
                            + " is not an DerivedUnit.");
2539
                }
2540
            }
2541

    
2542
            state.getProcessor().put(table, specimen, csvLine);
2543
        } catch (Exception e) {
2544
            state.getResult().addException(e, "An unexpected error occurred when handling specimen "
2545
                    + cdmBaseStr(specimen) + ": " + e.getMessage());
2546
        }
2547
    }
2548

    
2549
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
2550

    
2551
        String mediaUriString = "";
2552
        boolean first = true;
2553
        while (it.hasNext()) {
2554
            MediaRepresentation rep = it.next();
2555
            List<MediaRepresentationPart> parts = rep.getParts();
2556
            for (MediaRepresentationPart part : parts) {
2557
                if (first) {
2558
                    if (part.getUri() != null) {
2559
                        mediaUriString += part.getUri().toString();
2560
                        first = false;
2561
                    }
2562
                } else {
2563
                    if (part.getUri() != null) {
2564
                        mediaUriString += ", " + part.getUri().toString();
2565
                    }
2566
                }
2567
            }
2568
        }
2569

    
2570
        return mediaUriString;
2571
    }
2572

    
2573
    private String extractLinkUris(Iterator<ExternalLink> it) {
2574

    
2575
        String linkUriString = "";
2576
        boolean first = true;
2577
        while (it.hasNext()) {
2578
            ExternalLink link = it.next();
2579
            if (first) {
2580
                if (link.getUri() != null) {
2581
                    linkUriString += link.getUri().toString();
2582
                    first = false;
2583
                }
2584
            } else {
2585
                if (link.getUri() != null) {
2586
                    linkUriString += ", " + link.getUri().toString();
2587
                }
2588
            }
2589
        }
2590
        return linkUriString;
2591
    }
2592

    
2593
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2594
        try {
2595
            String collectorString = "";
2596
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2597
            if (gathering.getCollector() != null) {
2598
                if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2599

    
2600
                    Person primaryCollector = fieldUnit.getPrimaryCollector();
2601
                    if (collectorA instanceof Team) {
2602
                        Team collectorTeam = (Team) collectorA;
2603
                        boolean isFirst = true;
2604
                        for (Person member : collectorTeam.getTeamMembers()) {
2605
                            if (!isFirst) {
2606
                                collectorString += "; ";
2607
                            }
2608
                            if (member.equals(primaryCollector)) {
2609
                                // highlight
2610
                                collectorString += "<b>" + member.getTitleCache() + "</b>";
2611
                            } else {
2612
                                collectorString += member.getTitleCache();
2613
                            }
2614
                        }
2615
                    }
2616
                } else {
2617
                    collectorString = collectorA.getTitleCache();
2618
                }
2619
            }
2620
            return collectorString;
2621
        } catch (Exception e) {
2622
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2623
                    + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2624
            return "";
2625
        }
2626
    }
2627

    
2628
    /**
2629
     * Returns a string representation of the {@link CdmBase cdmBase} object for
2630
     * result messages.
2631
     */
2632
    private String cdmBaseStr(CdmBase cdmBase) {
2633
        if (cdmBase == null) {
2634
            return "-no object available-";
2635
        } else {
2636
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2637
        }
2638
    }
2639

    
2640
    @Override
2641
    protected boolean doCheck(CdmLightExportState state) {
2642
        return false;
2643
    }
2644

    
2645
    @Override
2646
    protected boolean isIgnore(CdmLightExportState state) {
2647
        return false;
2648
    }
2649

    
2650
}
(1-1/6)