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
    private IEditGeoService geoService;
120

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
258
                    // add root to node map
259

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

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

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

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

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

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

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

    
327

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
539
            try {
540

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

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

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

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

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

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

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

    
595
    }
596

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

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

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

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

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

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

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

    
676
                if (element instanceof IndividualsAssociation) {
677

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

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

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

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

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

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

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

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

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

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

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

    
778
    }
779

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
952
            Reference secRef = ppSyonym.getSec();
953

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

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

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

    
993
            // pro parte type
994

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

    
1005
    }
1006

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

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

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

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

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

    
1057

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

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

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

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

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

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

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

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

    
1107
            }
1108

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

    
1111
            Reference nomRef = name.getNomenclaturalReference();
1112

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

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

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

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

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

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

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

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

    
1248

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

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

    
1286

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

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

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

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

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

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

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

    
1319

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

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

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

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

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

    
1376

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

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

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

    
1449

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

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

    
1462

    
1463

    
1464

    
1465

    
1466
    }
1467

    
1468

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

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

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

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

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

    
1503
        rels = name.getRelationsToThisName();
1504

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

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

    
1515

    
1516
        }
1517
    }
1518

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

    
1532
        return collation;
1533
    }
1534

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

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

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

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

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

    
1580

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

    
1615

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1856

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

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

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

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

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

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

    
1899
                });
1900

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

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

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

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

    
1938

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

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

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

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

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

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

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

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

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

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

    
2065

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

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

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

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

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

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

    
2115
                        typeDesStateRefs += "]";
2116
                    }
2117

    
2118
            		typeTextDesignations =  typeTextDesignations + typeDesStateRefs +"; ";
2119

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

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

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

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

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

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

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

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

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

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

    
2207
        return typeDesignations;
2208
    }
2209

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

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

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

    
2252
            String exBasionymAuthorString = "";
2253

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2417
        } else if (authorship instanceof Team) {
2418

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

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

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

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

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

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

    
2479
                }
2480

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

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

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

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

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

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

    
2569
        return mediaUriString;
2570
    }
2571

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

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

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

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

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

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

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

    
2649
}
(1-1/6)