Project

General

Profile

Download (109 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.io.cdmLight;
10

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

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

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

    
101
/**
102
 * @author k.luther
103
 * @since 15.03.2017
104
 */
105
@Component
106
public class CdmLightClassificationExport
107
        extends CdmExportBase<CdmLightExportConfigurator, CdmLightExportState, IExportTransformer, File>{
108

    
109
    private static final long serialVersionUID = 2518643632756927053L;
110
    private static final String STD_TEAM_CONCATINATION = ", ";
111
    private static final String FINAL_TEAM_CONCATINATION = " & ";
112

    
113
    private static final String IPNI_NAME_IDENTIFIER = "Ipni Name Identifier";
114
    private static final String TROPICOS_NAME_IDENTIFIER = "Tropicos Name Identifier";
115
    private static final String WFO_NAME_IDENTIFIER = "WFO Name Identifier";
116

    
117
    @Autowired
118
    IEditGeoService geoService;
119

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

    
124
    }
125

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

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

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

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

    
150

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

    
154
            TaxonNode node = partitioner.next();
155
            while (node != null) {
156
                handleTaxonNode(state, node);
157
                node = partitioner.next();
158
            }
159
            // hole den rootKnoten und von dort aus die Helper Objekte
160
            // erzeugen...
161
            if (state.getRootId() != null) {
162
                List<TaxonNodeDto> childrenOfRoot = state.getNodeChildrenMap().get(state.getRootId());
163
                Comparator<TaxonNodeDto> comp = state.getConfig().getComparator();
164
                if (comp == null) {
165
                    comp = new TaxonNodeDtoByRankAndNameComparator();
166
                }
167
                if (childrenOfRoot != null) {
168
                    Collections.sort(childrenOfRoot, comp);
169
                    OrderHelper helper = new OrderHelper(state.getRootId());
170
                    helper.setOrderIndex(state.getActualOrderIndexAndUpdate());
171
                    state.getOrderHelperMap().put(state.getRootId(), helper);
172

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

    
180
                    }
181
                }
182

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

    
187
                }
188
            }
189

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

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

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

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

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

    
219
    }
220

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

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

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

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

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

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

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

    
292
    private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
293
        try {
294
            // Taxon taxon = taxonNode.getTaxon();
295
            if (taxonNode == null) {
296
                state.getResult().addError("The taxonNode was null.", "handleTaxon");
297
                state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
298
                return;
299
            }
300
            if (taxonNode.getTaxon() == null) {
301
                state.getResult().addError("There was a taxon node without a taxon: " + taxonNode.getUuid(),
302
                        "handleTaxon");
303
                state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
304
            } else {
305
                Taxon taxon = HibernateProxyHelper.deproxy(taxonNode.getTaxon(), Taxon.class);
306

    
307
                try {
308
                    TaxonName name = taxon.getName();
309
                    handleName(state, name);
310
                    for (Synonym syn : taxon.getSynonyms()) {
311
                        handleSynonym(state, syn);
312
                    }
313
                    for (TaxonRelationship rel : taxon.getProParteAndPartialSynonymRelations()) {
314
                        handleProPartePartialMisapplied(state, rel);
315
                    }
316
                    for (TaxonRelationship rel : taxon.getMisappliedNameRelations()) {
317
                        handleProPartePartialMisapplied(state, rel);
318
                    }
319

    
320
                    CdmLightExportTable table = CdmLightExportTable.TAXON;
321
                    String[] csvLine = new String[table.getSize()];
322

    
323
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_ID)] = getId(state, taxon);
324
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
325
                    Taxon parent = (taxonNode.getParent() == null) ? null : taxonNode.getParent().getTaxon();
326
                    csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
327
                    csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
328
                    if (taxon.getSec() != null && taxon.getSec().getDatePublished() != null
329
                            && taxon.getSec().getDatePublished().getFreeText() != null) {
330
                        String sec_string = taxon.getSec().getTitleCache() + ". "
331
                                + taxon.getSec().getDatePublished().getFreeText();
332
                        sec_string = sec_string.replace("..", ".");
333
                        csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = sec_string;
334
                    } else {
335
                        csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(taxon.getSec());
336
                    }
337
                    if (taxon.getSec() != null) {
338
                        if (!state.getReferenceStore().contains((taxon.getSec().getUuid()))) {
339
                            handleReference(state, taxon.getSec());
340
                        }
341
                    }
342
                    csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state,
343
                            taxonNode.getClassification());
344
                    csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification()
345
                            .getTitleCache();
346

    
347
                    csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = taxon.isPublish() ? "1" : "0";
348
                    csvLine[table.getIndex(CdmLightExportTable.EXCLUDED)] = taxonNode.isExcluded() ? "1" : "0";
349
                    Map<Language, LanguageString> notesMap = taxonNode.getStatusNote();
350
                    String statusNotes = "";
351
                    if (!notesMap.isEmpty() && notesMap.size() == 1) {
352
                        statusNotes = notesMap.values().iterator().next().getText();
353
                    } else if (!notesMap.isEmpty()) {
354
                        statusNotes = notesMap.get(Language.getDefaultLanguage()) != null
355
                                ? notesMap.get(Language.getDefaultLanguage()).getText() : null;
356
                        if (statusNotes == null) {
357
                            statusNotes = notesMap.values().iterator().next().getText();
358
                        }
359
                    }
360
                    csvLine[table.getIndex(CdmLightExportTable.STATUS_NOTES)] = statusNotes;
361

    
362
                    csvLine[table.getIndex(CdmLightExportTable.UNPLACED)] = taxonNode.isUnplaced() ? "1" : "0";
363
                    csvLine[table.getIndex(CdmLightExportTable.DOUBTFUL)] = taxonNode.isDoubtful() ? "1" : "0";
364
                    state.getProcessor().put(table, taxon, csvLine);
365
                    handleDescriptions(state, taxon);
366
                } catch (Exception e) {
367
                    state.getResult().addException(e,
368
                            "An unexpected problem occurred when trying to export taxon with id " + taxon.getId());
369
                    state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
370
                }
371
            }
372

    
373
            taxonNode.removeNullValueFromChildren();
374
            // for (TaxonNode child: taxonNode.getChildNodes()){
375
            // handleTaxon(state, child);
376
            // }
377
        } catch (Exception e) {
378
            state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
379
                    + cdmBaseStr(taxonNode.getTaxon()) + ": " + e.getMessage());
380
        }
381
    }
382

    
383
    private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
384
        try {
385
            if (cdmBase instanceof Taxon) {
386
                Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
387
                Set<TaxonDescription> descriptions = taxon.getDescriptions();
388
                List<DescriptionElementBase> simpleFacts = new ArrayList<>();
389
                List<DescriptionElementBase> specimenFacts = new ArrayList<>();
390
                List<DescriptionElementBase> distributionFacts = new ArrayList<>();
391
                List<DescriptionElementBase> taxonInteractionsFacts = new ArrayList<>();
392
                List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
393
                List<DescriptionElementBase> usageFacts = new ArrayList<>();
394
                for (TaxonDescription description : descriptions) {
395
                    if (description.getElements() != null) {
396
                        for (DescriptionElementBase element : description.getElements()) {
397
                            element = CdmBase.deproxy(element);
398
                            handleAnnotations(element);
399
                            if (element.getFeature().equals(Feature.COMMON_NAME())) {
400
                                commonNameFacts.add(element);
401
                            } else if (element.getFeature().equals(Feature.DISTRIBUTION())) {
402
                                distributionFacts.add(element);
403
                            } else if (element instanceof IndividualsAssociation
404
                                    || isSpecimenFeature(element.getFeature())) {
405
                                specimenFacts.add(element);
406
                            } else if (element.getFeature().isSupportsTaxonInteraction()) {
407
                                taxonInteractionsFacts.add(element);
408
                            } else {
409
                                simpleFacts.add(element);
410
                            }
411
                        }
412
                    }
413
                }
414
                if (!commonNameFacts.isEmpty()) {
415
                    handleCommonNameFacts(state, taxon, commonNameFacts);
416
                }
417
                if (!distributionFacts.isEmpty()) {
418
                    handleDistributionFacts(state, taxon, distributionFacts);
419
                }
420
                if (!specimenFacts.isEmpty()) {
421
                    handleSpecimenFacts(state, taxon, specimenFacts);
422
                }
423
                if (!simpleFacts.isEmpty()) {
424
                    handleSimpleFacts(state, taxon, simpleFacts);
425
                }
426
                if (!taxonInteractionsFacts.isEmpty()) {
427
                    handleTaxonInteractionsFacts(state, taxon, taxonInteractionsFacts);
428
                }
429
            } else if (cdmBase instanceof TaxonName) {
430
                TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
431
                Set<TaxonNameDescription> descriptions = name.getDescriptions();
432
                List<DescriptionElementBase> simpleFacts = new ArrayList<>();
433
                for (TaxonNameDescription description : descriptions) {
434
                    if (description.getElements() != null) {
435
                        for (DescriptionElementBase element : description.getElements()) {
436
                            simpleFacts.add(element);
437

    
438
                        }
439
                    }
440
                }
441
                if (!simpleFacts.isEmpty()) {
442
                    handleSimpleFacts(state, name, simpleFacts);
443
                }
444
            }
445
        } catch (Exception e) {
446
            state.getResult().addException(e, "An unexpected error occurred when handling description of"
447
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
448
        }
449
    }
450

    
451
    private void handleAnnotations(DescriptionElementBase element) {
452
        // TODO Auto-generated method stub
453
    }
454

    
455
    private void handleMetaData(CdmLightExportState state) {
456
        CdmLightExportTable table = CdmLightExportTable.METADATA;
457
        String[] csvLine = new String[table.getSize()];
458
//        csvLine[table.getIndex(CdmLightExportTable.INSTANCE_ID)] = state.getConfig().getInctanceId();
459
//        csvLine[table.getIndex(CdmLightExportTable.INSTANCE_NAME)] = state.getConfig().getInstanceName();
460
        csvLine[table.getIndex(CdmLightExportTable.DATASET_BASE_URL)] = state.getConfig().getBase_url();
461
        csvLine[table.getIndex(CdmLightExportTable.DATASET_CONTRIBUTOR)] = state.getConfig().getContributor();
462
        csvLine[table.getIndex(CdmLightExportTable.DATASET_CREATOR)] = state.getConfig().getCreator();
463
        csvLine[table.getIndex(CdmLightExportTable.DATASET_DESCRIPTION)] = state.getConfig().getDescription();
464
        csvLine[table.getIndex(CdmLightExportTable.DATASET_DOWNLOAD_LINK)] = state.getConfig().getDataset_download_link();
465
        csvLine[table.getIndex(CdmLightExportTable.DATASET_KEYWORDS)] = state.getConfig().getKeywords();
466
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANDINGPAGE)] = state.getConfig().getDataSet_landing_page();
467

    
468
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
469
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
470
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
471
        csvLine[table.getIndex(CdmLightExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
472
        csvLine[table.getIndex(CdmLightExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
473
        state.getProcessor().put(table, "", csvLine);
474
    }
475

    
476
    private boolean isSpecimenFeature(Feature feature) {
477
        // TODO allow user defined specimen features
478
        if (feature == null) {
479
            return false;
480
        } else if (feature.isSupportsIndividualAssociation()) {
481
            return true;
482
        } else {
483
            return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
484
                    || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
485
                    || feature.equals(Feature.OCCURRENCE());
486
        }
487
    }
488

    
489
    private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
490
            List<DescriptionElementBase> simpleFacts) {
491
        try {
492
            CdmLightExportTable table;
493
            if (cdmBase instanceof TaxonName) {
494
                table = CdmLightExportTable.NAME_FACT;
495
            } else {
496
                table = CdmLightExportTable.SIMPLE_FACT;
497
            }
498
            CdmLightExportTable tableMedia = CdmLightExportTable.MEDIA;
499
            for (DescriptionElementBase element : simpleFacts) {
500
                if (element.getModifyingText().isEmpty() && !element.getMedia().isEmpty()) {
501
                    handleSimpleMediaFact(state, cdmBase, tableMedia, element);
502
                } else {
503
                    handleSingleSimpleFact(state, cdmBase, table, element);
504
                }
505
            }
506
        } catch (Exception e) {
507
            state.getResult().addException(e, "An unexpected error occurred when handling simple facts for "
508
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
509
        }
510
    }
511

    
512
    private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
513
            List<DescriptionElementBase> taxonInteractionsFacts) {
514
        CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
515
        for (DescriptionElementBase element : taxonInteractionsFacts) {
516
            try {
517

    
518
                String[] csvLine = new String[table.getSize()];
519

    
520
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
521
                handleSource(state, element, table);
522
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
523
                csvLine[table.getIndex(CdmLightExportTable.TAXON2_FK)] = getId(state,
524
                        ((TaxonInteraction) element).getTaxon2());
525
                csvLine[table.getIndex(CdmLightExportTable.DESCRIPTION)] = createMultilanguageString(
526
                        ((TaxonInteraction) element).getDescription());
527
                state.getProcessor().put(table, element, csvLine);
528

    
529
            } catch (Exception e) {
530
                state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
531
                        + cdmBaseStr(element) + ": " + e.getMessage());
532
            }
533
        }
534
    }
535

    
536
    private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
537
            DescriptionElementBase element) {
538
        try {
539
            String[] csvLine;
540
            handleSource(state, element, CdmLightExportTable.MEDIA);
541

    
542
            if (element instanceof TextData) {
543
                TextData textData = (TextData) element;
544
                csvLine = new String[table.getSize()];
545
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
546
                if (cdmBase instanceof Taxon) {
547
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
548
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
549
                } else if (cdmBase instanceof TaxonName) {
550
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
551
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
552
                }
553

    
554
                String mediaUris = "";
555
                for (Media media : textData.getMedia()) {
556
                    String mediaString = extractMediaUris(media.getRepresentations().iterator());
557
                    if (!StringUtils.isBlank(mediaString)) {
558
                        mediaUris += mediaString + ";";
559
                    } else {
560
                        state.getResult().addWarning("Empty Media object for " + cdmBase.getUserFriendlyTypeName() + " "
561
                                + cdmBase.getUuid() + " (media: " + media.getUuid() + ")");
562
                    }
563
                }
564
                csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
565

    
566
            }
567
        } catch (Exception e) {
568
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
569
                    + cdmBaseStr(element) + ": " + e.getMessage());
570
        }
571

    
572
    }
573

    
574
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
575
            DescriptionElementBase element) {
576
        try {
577
            String[] csvLine;
578
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
579

    
580
            if (element instanceof TextData) {
581
                TextData textData = (TextData) element;
582
                csvLine = new String[table.getSize()];
583
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
584
                if (cdmBase instanceof Taxon) {
585
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
586
                    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] =
587
                    // "";
588
                } else if (cdmBase instanceof TaxonName) {
589
                    // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] =
590
                    // "";
591
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
592
                }
593
                csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
594

    
595
                String mediaUris = "";
596
                for (Media media : textData.getMedia()) {
597
                    String mediaString = extractMediaUris(media.getRepresentations().iterator());
598
                    if (!StringUtils.isBlank(mediaString)) {
599
                        mediaUris += mediaString + ";";
600
                    } else {
601
                        state.getResult().addWarning("Empty Media object for uuid: " + cdmBase.getUuid()
602
                                + " uuid of media: " + media.getUuid());
603
                    }
604
                }
605
                csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
606
                if (textData.getFeature().equals(Feature.CITATION())) {
607
                    // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] =
608
                    // getId(state, cdmBase);
609
                    state.getProcessor().put(table, textData, csvLine);
610
                } else if (!textData.getMultilanguageText().isEmpty()) {
611
                    for (Language language : textData.getMultilanguageText().keySet()) {
612
                        String[] csvLineLanguage = csvLine.clone();
613
                        LanguageString langString = textData.getLanguageText(language);
614
                        String text = langString.getText();
615
                        if (state.getConfig().isFilterIntextReferences()) {
616
                            text = filterIntextReferences(langString.getText());
617
                        }
618
                        csvLineLanguage[table.getIndex(CdmLightExportTable.FACT_TEXT)] = text;
619
                        csvLineLanguage[table.getIndex(CdmLightExportTable.LANGUAGE)] = language.getLabel();
620
                        state.getProcessor().put(table, textData, csvLineLanguage);
621
                    }
622
                } else {
623
                    state.getProcessor().put(table, textData, csvLine);
624
                }
625
            }
626
        } catch (Exception e) {
627
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
628
                    + cdmBaseStr(element) + ": " + e.getMessage());
629
        }
630
    }
631

    
632
    private String filterIntextReferences(String text) {
633
        /*
634
         * (<cdm:reference cdmId='fbd19251-efee-4ded-b780-915000f66d41'
635
         * intextId='1352d42c-e201-4155-a02a-55360d3b563e'>Ridley in Fl. Malay
636
         * Pen. 3 (1924) 22</cdm:reference>)
637
         */
638

    
639
        String newText = text.replaceAll("<cdm:reference cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
640
        newText = newText.replaceAll("</cdm:reference>", "");
641

    
642
        newText = newText.replaceAll("<cdm:key cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
643
        newText = newText.replaceAll("</cdm:key>", "");
644
        return newText;
645
    }
646

    
647
    private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon,
648
            List<DescriptionElementBase> specimenFacts) {
649
        CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
650

    
651
        for (DescriptionElementBase element : specimenFacts) {
652
            try {
653
                String[] csvLine = new String[table.getSize()];
654
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
655
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
656
                handleSource(state, element, table);
657
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(
658
                        element.getAnnotations());
659

    
660
                if (element instanceof IndividualsAssociation) {
661

    
662
                    IndividualsAssociation indAssociation = (IndividualsAssociation) element;
663
                    if (indAssociation.getAssociatedSpecimenOrObservation() == null) {
664
                        state.getResult()
665
                                .addWarning("There is an individual association with no specimen associated (Taxon "
666
                                        + taxon.getTitleCache() + "(" + taxon.getUuid() + "). Could not be exported.");
667
                        continue;
668
                    } else {
669
                        if (!state.getSpecimenStore()
670
                                .contains((indAssociation.getAssociatedSpecimenOrObservation().getUuid()))) {
671
                            SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(
672
                                    indAssociation.getAssociatedSpecimenOrObservation(),
673
                                    SpecimenOrObservationBase.class);
674

    
675
                            handleSpecimen(state, specimenBase);
676
                            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
677
                                    indAssociation.getAssociatedSpecimenOrObservation());
678

    
679
                        }
680
                    }
681
                } else if (element instanceof TextData) {
682
                    TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
683
                    csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(
684
                            textData.getMultilanguageText());
685
                }
686
                state.getProcessor().put(table, element, csvLine);
687
            } catch (Exception e) {
688
                state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact "
689
                        + cdmBaseStr(element) + ": " + e.getMessage());
690
            }
691
        }
692
    }
693

    
694
    private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
695
        String text = "";
696
        int index = multilanguageText.size();
697
        for (LanguageString langString : multilanguageText.values()) {
698
            text += langString.getText();
699
            if (index > 1) {
700
                text += "; ";
701
            }
702
            index--;
703
        }
704
        return text;
705
    }
706

    
707
    private String createAnnotationsString(Set<Annotation> annotations) {
708
        StringBuffer strBuff = new StringBuffer();
709

    
710
        for (Annotation ann : annotations) {
711
            if (ann.getAnnotationType() == null || !ann.getAnnotationType().equals(AnnotationType.TECHNICAL())) {
712
                strBuff.append(ann.getText());
713
                strBuff.append("; ");
714
            }
715
        }
716

    
717
        if (strBuff.length() > 2) {
718
            return strBuff.substring(0, strBuff.length() - 2);
719
        } else {
720
            return null;
721
        }
722
    }
723

    
724
    private void handleSource(CdmLightExportState state, DescriptionElementBase element,
725
            CdmLightExportTable factsTable) {
726
        CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
727
        try {
728
            Set<DescriptionElementSource> sources = element.getSources();
729

    
730
            for (DescriptionElementSource source : sources) {
731
                if (!(source.getType().equals(OriginalSourceType.Import)
732
                        && state.getConfig().isFilterImportSources())) {
733
                    String[] csvLine = new String[table.getSize()];
734
                    Reference ref = source.getCitation();
735
                    if ((ref == null) && (source.getNameUsedInSource() == null)) {
736
                        continue;
737
                    }
738
                    if (ref != null) {
739
                        if (!state.getReferenceStore().contains(ref.getUuid())) {
740
                            handleReference(state, ref);
741

    
742
                        }
743
                        csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
744
                    }
745
                    csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
746

    
747
                    csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state,
748
                            source.getNameUsedInSource());
749
                    csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
750
                    if (StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])
751
                            && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])) {
752
                        continue;
753
                    }
754
                    state.getProcessor().put(table, source, csvLine);
755
                }
756

    
757
            }
758
        } catch (Exception e) {
759
            state.getResult().addException(e, "An unexpected error occurred when handling single source "
760
                    + cdmBaseStr(element) + ": " + e.getMessage());
761
        }
762

    
763
    }
764

    
765
    private void handleDistributionFacts(CdmLightExportState state, Taxon taxon,
766
            List<DescriptionElementBase> distributionFacts) {
767
        CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
768
        Set<Distribution> distributions = new HashSet<>();
769
        for (DescriptionElementBase element : distributionFacts) {
770
            try {
771
                if (element instanceof Distribution) {
772
                    String[] csvLine = new String[table.getSize()];
773
                    Distribution distribution = (Distribution) element;
774
                    distributions.add(distribution);
775
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
776
                    handleSource(state, element, table);
777
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
778
                    if (distribution.getArea() != null) {
779
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = distribution.getArea().getLabel();
780
                    }
781
                    if (distribution.getStatus() != null) {
782
                        csvLine[table.getIndex(CdmLightExportTable.STATUS_LABEL)] = distribution.getStatus().getLabel();
783
                    }
784
                    state.getProcessor().put(table, distribution, csvLine);
785
                } else {
786
                    state.getResult()
787
                            .addError("The distribution description for the taxon " + taxon.getUuid()
788
                                    + " is not of type distribution. Could not be exported. UUID of the description element: "
789
                                    + element.getUuid());
790
                }
791
            } catch (Exception e) {
792
                state.getResult().addException(e, "An unexpected error occurred when handling single distribution "
793
                        + cdmBaseStr(element) + ": " + e.getMessage());
794
            }
795
        }
796
        // if(state.getConfig().isCreateCondensedDistributionString()){
797
        // List<Language> langs = new ArrayList<Language>();
798
        // langs.add(Language.ENGLISH());
799
        //
800
        // CondensedDistribution conDis =
801
        // geoService.getCondensedDistribution(distributions, true,
802
        // null,null,state.getConfig().getCondensedDistributionRecipe(), langs
803
        // );
804
        // CdmLightExportTable tableCondensed =
805
        // CdmLightExportTable.CONDENSED_DISTRIBUTION_FACT;
806
        // String[] csvLine = new String[table.getSize()];
807
        // csvLine[tableCondensed.getIndex(CdmLightExportTable.TAXON_FK)] =
808
        // getId(state, taxon);
809
        // csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
810
        // conDis.toString();
811
        // state.getProcessor().put(tableCondensed, taxon, csvLine);
812
        // }
813

    
814
    }
815

    
816
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
817
            List<DescriptionElementBase> commonNameFacts) {
818
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
819

    
820
        for (DescriptionElementBase element : commonNameFacts) {
821
            try {
822
                if (element instanceof CommonTaxonName) {
823
                    String[] csvLine = new String[table.getSize()];
824
                    CommonTaxonName commonName = (CommonTaxonName) element;
825
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
826
                    handleSource(state, element, table);
827
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
828
                    if (commonName.getName() != null) {
829
                        csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();
830
                    }
831
                    if (commonName.getLanguage() != null) {
832
                        csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();
833
                    }
834
                    if (commonName.getArea() != null) {
835
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();
836
                    }
837
                    state.getProcessor().put(table, commonName, csvLine);
838
                } else {
839
                    state.getResult()
840
                            .addError("The distribution description for the taxon " + taxon.getUuid()
841
                                    + " is not of type distribution. Could not be exported. UUID of the description element: "
842
                                    + element.getUuid());
843
                }
844
            } catch (Exception e) {
845
                state.getResult().addException(e, "An unexpected error occurred when handling single common name "
846
                        + cdmBaseStr(element) + ": " + e.getMessage());
847
            }
848
        }
849
    }
850

    
851
    /**
852
     * @param sec
853
     * @return
854
     */
855
    private String getTitleCache(IIdentifiableEntity identEntity) {
856
        if (identEntity == null) {
857
            return "";
858
        }
859
        // TODO refresh?
860
        return identEntity.getTitleCache();
861
    }
862

    
863
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
864
        if (cdmBase == null) {
865
            return "";
866
        }
867
        // TODO make configurable
868
        return cdmBase.getUuid().toString();
869
    }
870

    
871
    private void handleSynonym(CdmLightExportState state, Synonym synonym) {
872
        try {
873
            if (isUnpublished(state.getConfig(), synonym)) {
874
                return;
875
            }
876
            TaxonName name = synonym.getName();
877
            handleName(state, name);
878

    
879
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
880
            String[] csvLine = new String[table.getSize()];
881

    
882
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, synonym);
883
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, synonym.getAcceptedTaxon());
884
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
885
            if (synonym.getSec() != null && !state.getReferenceStore().contains(synonym.getSec().getUuid())) {
886
                handleReference(state, synonym.getSec());
887
            }
888
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synonym.getSec());
889
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synonym.getSec());
890
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = synonym.isPublish() ? "1" : "0";
891
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = "0";
892
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = "0";
893
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = "0";
894
            state.getProcessor().put(table, synonym, csvLine);
895
        } catch (Exception e) {
896
            state.getResult().addException(e, "An unexpected error occurred when handling synonym "
897
                    + cdmBaseStr(synonym) + ": " + e.getMessage());
898
        }
899
    }
900

    
901
    /**
902
     * Handles Misapplied names (including pro parte and partial as well as pro
903
     * parte and partial synonyms
904
     *
905
     * @param state
906
     * @param rel
907
     */
908
    private void handleProPartePartialMisapplied(CdmLightExportState state, TaxonRelationship rel) {
909
        try {
910
            Taxon ppSyonym = rel.getFromTaxon();
911
            if (isUnpublished(state.getConfig(), ppSyonym)) {
912
                return;
913
            }
914
            TaxonName name = ppSyonym.getName();
915
            handleName(state, name);
916

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

    
920
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, rel);
921
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, rel.getToTaxon());
922
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
923

    
924
            Reference secRef = ppSyonym.getSec();
925
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
926
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
927
            Reference synSecRef = rel.getCitation();
928
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
929
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
930

    
931
            // pro parte type
932
            TaxonRelationshipType type = rel.getType();
933
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = type.isProParte() ? "1" : "0";
934
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = type.isPartial() ? "1" : "0";
935
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = type.isAnyMisappliedName() ? "1" : "0";
936

    
937
            state.getProcessor().put(table, ppSyonym, csvLine);
938
        } catch (Exception e) {
939
            state.getResult().addException(e, "An unexpected error occurred when handling "
940
                    + "pro parte/partial synonym relationship " + cdmBaseStr(rel) + ": " + e.getMessage());
941
        }
942

    
943
    }
944

    
945
    private void handleName(CdmLightExportState state, TaxonName name) {
946
        if (name == null || state.getNameStore().containsKey(name.getId())) {
947
            return;
948
        }
949
        try {
950
            Rank rank = name.getRank();
951
            CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
952
            name = HibernateProxyHelper.deproxy(name);
953
            state.getNameStore().put(name.getId(), name.getUuid());
954
            String[] csvLine = new String[table.getSize()];
955

    
956
            csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
957
            if (name.getLsid() != null) {
958
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
959
            } else {
960
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
961
            }
962

    
963
            handleIdentifier(state, name);
964
            handleDescriptions(state, name);
965

    
966
            csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
967
            if (rank != null) {
968
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
969
                if (rank.isInfraGeneric()) {
970
                    try {
971
                        csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank()
972
                                .getInfraGenericMarker();
973
                    } catch (UnknownCdmTypeException e) {
974
                        state.getResult().addError("Infrageneric marker expected but not available for rank "
975
                                + name.getRank().getTitleCache());
976
                    }
977
                }
978
                if (rank.isInfraSpecific()) {
979
                    csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
980
                }
981
            } else {
982
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
983
            }
984
            if (name.isProtectedTitleCache()) {
985
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
986
            } else {
987
                // TODO: adapt the tropicos titlecache creation
988
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
989
            }
990
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
991
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
992

    
993
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
994
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
995

    
996
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
997
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
998
            if (name.getBasionymAuthorship() != null) {
999
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
1000
                    handleAuthor(state, name.getBasionymAuthorship());
1001
                }
1002
            }
1003
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state,
1004
                    name.getExBasionymAuthorship());
1005
            if (name.getExBasionymAuthorship() != null) {
1006
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
1007
                    handleAuthor(state, name.getExBasionymAuthorship());
1008
                }
1009

    
1010
            }
1011
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,
1012
                    name.getCombinationAuthorship());
1013
            if (name.getCombinationAuthorship() != null) {
1014
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
1015
                    handleAuthor(state, name.getCombinationAuthorship());
1016
                }
1017
            }
1018
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state,
1019
                    name.getExCombinationAuthorship());
1020
            if (name.getExCombinationAuthorship() != null) {
1021
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
1022
                    handleAuthor(state, name.getExCombinationAuthorship());
1023
                }
1024

    
1025
            }
1026

    
1027
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
1028

    
1029
            Reference nomRef = name.getNomenclaturalReference();
1030

    
1031
            if (nomRef != null) {
1032
                if (!state.getReferenceStore().contains(nomRef.getUuid())) {
1033
                    handleReference(state, nomRef);
1034
                }
1035
                csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
1036
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
1037
                if (nomRef.getVolume() != null) {
1038
                    csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
1039
                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
1040
                }
1041
                if (nomRef.getDatePublished() != null) {
1042
                    csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
1043
                    csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
1044
                    csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = nomRef.getDatePublished()
1045
                            .getVerbatimDate();
1046
                }
1047
                if (name.getNomenclaturalMicroReference() != null) {
1048
                    csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
1049
                }
1050
                nomRef = HibernateProxyHelper.deproxy(nomRef);
1051
                if (nomRef.getInReference() != null) {
1052
                    Reference inReference = nomRef.getInReference();
1053
                    if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null) {
1054
                        csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference
1055
                                .getDatePublishedString();
1056
                        csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished()
1057
                                .getYear();
1058
                    }
1059
                    if (nomRef.getVolume() == null && inReference.getVolume() != null) {
1060
                        csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
1061
                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
1062
                    }
1063
                    if (inReference.getInReference() != null) {
1064
                        inReference = inReference.getInReference();
1065
                    }
1066
                    if (inReference.getAbbrevTitle() == null) {
1067
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1068
                                .Nz(inReference.getAbbrevTitleCache());
1069
                    } else {
1070
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1071
                                .Nz(inReference.getAbbrevTitle());
1072
                    }
1073
                    if (inReference.getTitle() == null) {
1074
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils
1075
                                .Nz(inReference.getTitleCache());
1076
                    } else {
1077
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
1078
                    }
1079

    
1080
                    TeamOrPersonBase<?> author = inReference.getAuthorship();
1081
                    if (author != null
1082
                            && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))) {
1083
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1084
                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitle());
1085
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1086
                                .Nz(author.getTitleCache());
1087
                    } else {
1088
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1089
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1090
                    }
1091
                } else {
1092
                    if (nomRef.getAbbrevTitle() == null) {
1093
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1094
                                .Nz(nomRef.getAbbrevTitleCache());
1095
                    } else {
1096
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1097
                                .Nz(nomRef.getAbbrevTitle());
1098
                    }
1099
                    if (nomRef.getTitle() == null) {
1100
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitleCache());
1101
                    } else {
1102
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
1103
                    }
1104
                    TeamOrPersonBase<?> author = nomRef.getAuthorship();
1105
                    if (author != null) {
1106
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1107
                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitle());
1108
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1109
                                .Nz(author.getTitleCache());
1110
                    } else {
1111
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1112
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1113
                    }
1114

    
1115
                }
1116
            } else {
1117
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
1118
            }
1119

    
1120
            /*
1121
             * Collation
1122
             *
1123
             * Detail
1124
             *
1125
             *
1126
             * TitlePageYear
1127
             */
1128
            Set<TaxonNameDescription> descriptions = name.getDescriptions();
1129
            String protologueUriString = extractURIs(state, descriptions, Feature.PROTOLOGUE());
1130

    
1131
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
1132
            Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1133
            List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1134
            for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1135
                if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1136

    
1137
                    if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1138
                        Set<IdentifiableSource> sources =  typeDesignation.getSources();
1139
                        boolean isProtologue = false;
1140
                        if (sources != null && !sources.isEmpty()){
1141
                            IdentifiableSource source = sources.iterator().next();
1142
                            if (name.getNomenclaturalReference() != null){
1143
                                isProtologue = source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid());
1144
                            }
1145
                        }
1146
                        if (isProtologue){
1147
                            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_TYPE_STATEMENT)] = ((TextualTypeDesignation) typeDesignation)
1148
                                    .getPreferredText(Language.DEFAULT());
1149
                        }else{
1150
                            textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1151
                        }
1152

    
1153
                    } else {
1154
                        textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1155
                    }
1156
                } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1157

    
1158
                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class));
1159

    
1160
                }
1161
            }
1162
            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
1163
            String typeDesignationString = createTypeDesignationString(manager.toTaggedText(), false);
1164
            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = typeDesignationString;
1165

    
1166
            StringBuilder stringbuilder = new StringBuilder();
1167
            int i = 1;
1168
            for (TextualTypeDesignation typeDesignation : textualTypeDesignations) {
1169
                stringbuilder.append(typeDesignation.getPreferredText(Language.DEFAULT()));
1170
                if (typeDesignation.getSources() != null && !typeDesignation.getSources().isEmpty() ){
1171
                    stringbuilder.append( " [");
1172
                    int index = 1;
1173
                    for (IdentifiableSource source: typeDesignation.getSources()){
1174
                        if (source.getCitation() != null){
1175
                            stringbuilder.append(((DefaultReferenceCacheStrategy)source.getCitation().getCacheStrategy()).getCitation(source.getCitation()));
1176
                        }
1177
                        if (index < typeDesignation.getSources().size()) {
1178
                            stringbuilder.append( ", ");
1179
                        }
1180
                        index++;
1181
                    }
1182
                    stringbuilder.append( "]");
1183
                }
1184
                if (i < textualTypeDesignations.size()) {
1185
                    stringbuilder.append( "; ");
1186
                } else {
1187
                    stringbuilder.append(".");
1188
                }
1189
                i++;
1190
            }
1191
            csvLine[table.getIndex(CdmLightExportTable.TYPE_STATEMENT)] = stringbuilder.toString();
1192

    
1193

    
1194
            if (name.getStatus() == null || name.getStatus().isEmpty()) {
1195
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
1196
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
1197
            } else {
1198

    
1199
                String statusStringAbbrev = extractStatusString(state, name, true);
1200
                String statusString = extractStatusString(state, name, false);
1201

    
1202
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
1203
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
1204
            }
1205

    
1206
            HomotypicalGroup group = name.getHomotypicalGroup();
1207

    
1208
            if (!state.containsHomotypicalGroupFromStore(group.getUuid())) {
1209
                handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
1210
            }
1211
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
1212
            List<TaxonName> typifiedNames = new ArrayList<>();
1213
            typifiedNames.addAll(group.getTypifiedNames());
1214
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1215
            Integer seqNumber = typifiedNames.indexOf(name);
1216
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1217
            state.getProcessor().put(table, name, csvLine);
1218
            handleNameRelationships(state, name);
1219

    
1220
        } catch (Exception e) {
1221
            state.getResult().addException(e,
1222
                    "An unexpected error occurred when handling synonym " + cdmBaseStr(name) + ": " + e.getMessage());
1223

    
1224
            e.printStackTrace();
1225
        }
1226
    }
1227

    
1228
    private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1229
        Set<NameRelationship> rels = name.getRelationsFromThisName();
1230
        CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1231
        String[] csvLine = new String[table.getSize()];
1232

    
1233
        for (NameRelationship rel : rels) {
1234
            NameRelationshipType type = rel.getType();
1235
            TaxonName name2 = rel.getToName();
1236
            if (!state.getNameStore().containsKey(name2.getId())) {
1237
                handleName(state, name2);
1238
            }
1239

    
1240
            csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1241
            csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1242
            csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1243
            state.getProcessor().put(table, name, csvLine);
1244
        }
1245

    
1246
    }
1247

    
1248
    private String createCollatation(TaxonName name) {
1249
        String collation = "";
1250
        if (name.getNomenclaturalReference() != null) {
1251
            Reference ref = name.getNomenclaturalReference();
1252
            collation = getVolume(ref);
1253
        }
1254
        if (name.getNomenclaturalMicroReference() != null) {
1255
            if (!StringUtils.isBlank(collation)) {
1256
                collation += ":";
1257
            }
1258
            collation += name.getNomenclaturalMicroReference();
1259
        }
1260

    
1261
        return collation;
1262
    }
1263

    
1264
    private String getVolume(Reference reference) {
1265
        if (reference.getVolume() != null) {
1266
            return reference.getVolume();
1267
        } else if (reference.getInReference() != null) {
1268
            if (reference.getInReference().getVolume() != null) {
1269
                return reference.getInReference().getVolume();
1270
            }
1271
        }
1272
        return null;
1273
    }
1274

    
1275
    private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1276
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1277
        String[] csvLine;
1278
        try {
1279
            if (cdmBase instanceof TaxonName){
1280
                TaxonName name = (TaxonName)cdmBase;
1281

    
1282
                try{
1283
                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1284
                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1285
                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1286
                    if (!IPNIidentifiers.isEmpty()) {
1287
                        csvLine = new String[table.getSize()];
1288
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1289
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1290
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1291
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1292
                                IPNIidentifiers);
1293
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1294
                    }
1295
                    if (!tropicosIdentifiers.isEmpty()) {
1296
                        csvLine = new String[table.getSize()];
1297
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1298
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1299
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = name.getUuid() + ", " + IPNI_NAME_IDENTIFIER;
1300
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1301
                                tropicosIdentifiers);
1302
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1303
                    }
1304
                    if (!WFOIdentifiers.isEmpty()) {
1305
                        csvLine = new String[table.getSize()];
1306
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1307
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1308
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1309
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1310
                                WFOIdentifiers);
1311
                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1312
                    }
1313
                }catch(Exception e){
1314
                    state.getResult().addWarning("Please check the identifiers for "
1315
                            + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1316

    
1317

    
1318
                }
1319
            }else{
1320
                if (cdmBase instanceof IdentifiableEntity){
1321
                    IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1322
                    List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1323
                    String tableName = null;
1324
                    if (cdmBase instanceof Reference){
1325
                        tableName = "Reference";
1326
                    }else if (cdmBase instanceof SpecimenOrObservationBase){
1327
                        tableName = "Specimen";
1328
                    }else if (cdmBase instanceof Taxon){
1329
                        tableName = "Taxon";
1330
                    }else if (cdmBase instanceof Synonym){
1331
                        tableName = "Synonym";
1332
                    }else if (cdmBase instanceof TeamOrPersonBase){
1333
                        tableName = "PersonOrTeam";
1334
                    }
1335

    
1336
                    for (Identifier identifier: identifiers){
1337
                        if (identifier.getType() == null && identifier.getIdentifier() == null){
1338
                            state.getResult().addWarning("Please check the identifiers for "
1339
                                    + cdmBaseStr(cdmBase) + " there is an empty identifier");
1340
                            continue;
1341
                        }
1342

    
1343
                        csvLine = new String[table.getSize()];
1344
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1345

    
1346
                        if (tableName != null){
1347
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1348
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1349
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1350
                            state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1351
                        }
1352
                    }
1353
                    if (cdmBase instanceof Reference ){
1354
                        Reference ref = (Reference)cdmBase;
1355
                        if (ref.getDoi() != null){
1356
                            csvLine = new String[table.getSize()];
1357
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1358
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1359
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1360
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1361
                            state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1362
                        }
1363
                    }
1364

    
1365
                    if (cdmBase instanceof TeamOrPersonBase){
1366
                        TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1367
                        if (person instanceof Person &&  ((Person)person).getOrcid() != null){
1368
                            csvLine = new String[table.getSize()];
1369
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1370
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1371
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1372
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]=  ((Person)person).getOrcid().asURI();
1373
                            state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1374
                        }
1375
                    }
1376
                }
1377
            }
1378
        } catch (Exception e) {
1379
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1380
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1381
            e.printStackTrace();
1382
        }
1383
    }
1384

    
1385
    private String extractIdentifier(Set<String> identifierSet) {
1386

    
1387
        String identifierString = "";
1388
        for (String identifier : identifierSet) {
1389
            if (!StringUtils.isBlank(identifierString)) {
1390
                identifierString += ", ";
1391
            }
1392
            identifierString += identifier;
1393
        }
1394
        return identifierString;
1395
    }
1396

    
1397
    private String extractURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1398
            Feature feature) {
1399
        String mediaUriString = "";
1400
        SpecimenDescription specimenDescription;
1401
        TaxonDescription taxonDescription;
1402
        TaxonNameDescription nameDescription;
1403
        Set<DescriptionElementBase> elements = new HashSet<>();
1404
        for (DescriptionBase<?> description : descriptionsSet) {
1405
            try {
1406
                if (!description.getElements().isEmpty()) {
1407
                    if (description instanceof SpecimenDescription) {
1408
                        specimenDescription = (SpecimenDescription) description;
1409
                        elements = specimenDescription.getElements();
1410
                    } else if (description instanceof TaxonDescription) {
1411
                        taxonDescription = (TaxonDescription) description;
1412
                        elements = taxonDescription.getElements();
1413
                    } else if (description instanceof TaxonNameDescription) {
1414
                        nameDescription = (TaxonNameDescription) description;
1415
                        elements = nameDescription.getElements();
1416
                    }
1417

    
1418
                    for (DescriptionElementBase element : elements) {
1419
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1420
                        if (entityFeature.equals(feature)) {
1421
                            if (!element.getMedia().isEmpty()) {
1422
                                List<Media> media = element.getMedia();
1423
                                for (Media mediaElement : media) {
1424
                                    Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1425
                                    mediaUriString = extractMediaUris(it);
1426
                                }
1427
                            }
1428
                        }
1429
                    }
1430
                }
1431
            } catch (Exception e) {
1432
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1433
                        + cdmBaseStr(description) + ": " + e.getMessage());
1434
            }
1435
        }
1436
        return mediaUriString;
1437
    }
1438

    
1439
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1440
        try {
1441
            if (state.getAuthorFromStore(author.getId()) != null) {
1442
                return;
1443
            }
1444
            state.addAuthorToStore(author);
1445
            handleIdentifier(state, author);
1446
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1447
            String[] csvLine = new String[table.getSize()];
1448
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1449
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
1450
            String[] csvLineMember = new String[table.getSize()];
1451
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1452
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1453
                    ? author.getTitleCache() : author.getNomenclaturalTitle();
1454
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1455
            author = HibernateProxyHelper.deproxy(author);
1456
            if (author instanceof Person) {
1457
                Person authorPerson = (Person) author;
1458
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1459
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1460
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1461
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1462
            } else {
1463
                // create an entry in rel table and all members in author table,
1464
                // check whether the team members already in author table
1465

    
1466
                Team authorTeam = (Team) author;
1467
                int index = 0;
1468
                for (Person member : authorTeam.getTeamMembers()) {
1469
                    csvLineRel = new String[tableAuthorRel.getSize()];
1470
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1471
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1472
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1473
                            .valueOf(index);
1474
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1475

    
1476
                    if (state.getAuthorFromStore(member.getId()) == null) {
1477
                        state.addAuthorToStore(member);
1478
                        csvLineMember = new String[table.getSize()];
1479
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1480
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1481
                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitle();
1482
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1483
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1484
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1485
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1486
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1487
                        state.getProcessor().put(table, member, csvLineMember);
1488
                    }
1489
                    index++;
1490
                }
1491
            }
1492
            state.getProcessor().put(table, author, csvLine);
1493
        } catch (Exception e) {
1494
            state.getResult().addException(e,
1495
                    "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1496
        }
1497
    }
1498

    
1499
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1500
        try {
1501
            Set<NomenclaturalStatus> status = name.getStatus();
1502
            if (status.isEmpty()) {
1503
                return "";
1504
            }
1505
            String statusString = "";
1506
            for (NomenclaturalStatus nameStatus : status) {
1507
                if (nameStatus != null) {
1508
                    if (abbrev) {
1509
                        if (nameStatus.getType() != null) {
1510
                            statusString += nameStatus.getType().getIdInVocabulary();
1511
                        }
1512
                    } else {
1513
                        if (nameStatus.getType() != null) {
1514
                            statusString += nameStatus.getType().getTitleCache();
1515
                        }
1516
                    }
1517
                    if (!abbrev) {
1518

    
1519
                        if (nameStatus.getRuleConsidered() != null
1520
                                && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1521
                            statusString += " " + nameStatus.getRuleConsidered();
1522
                        }
1523
                        if (nameStatus.getCitation() != null) {
1524
                            statusString += " " + nameStatus.getCitation().getTitleCache();
1525
                        }
1526
                        if (nameStatus.getCitationMicroReference() != null
1527
                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1528
                            statusString += " " + nameStatus.getCitationMicroReference();
1529
                        }
1530
                    }
1531
                    statusString += " ";
1532
                }
1533
            }
1534
            return statusString;
1535
        } catch (Exception e) {
1536
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1537
                    + cdmBaseStr(name) + ": " + e.getMessage());
1538
            return "";
1539
        }
1540
    }
1541

    
1542
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group) {
1543
        try {
1544
            state.addHomotypicalGroupToStore(group);
1545
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1546
            String[] csvLine = new String[table.getSize()];
1547

    
1548
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1549
            List<TaxonName> typifiedNames = new ArrayList<>();
1550
            typifiedNames.addAll(group.getTypifiedNames());
1551
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1552
            String typifiedNamesString = "";
1553
            for (TaxonName name : typifiedNames) {
1554
                // Concatenated output string for homotypic group (names and
1555
                // citations) + status + some name relations (e.g. “non”)
1556
                // TODO: nameRelations, which and how to display
1557

    
1558
                typifiedNamesString += name.getTitleCache() + extractStatusString(state, name, true) + "; ";
1559
            }
1560
            typifiedNamesString = typifiedNamesString.substring(0, typifiedNamesString.length() - 2);
1561
            if (typifiedNamesString != null) {
1562
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
1563
            } else {
1564
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
1565
            }
1566
            Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
1567
            List<TypeDesignationBase<?>> designationList = new ArrayList<>();
1568
            designationList.addAll(typeDesigantionSet);
1569
            Collections.sort(designationList, new TypeComparator());
1570

    
1571
            List<TaggedText> list = new ArrayList<>();
1572
            if (!designationList.isEmpty()) {
1573
                TypeDesignationSetManager manager = new TypeDesignationSetManager(group);
1574
                list.addAll(manager.toTaggedTextWithCitation());
1575
            }
1576
            String typeTextDesignations = "";
1577
            //The typeDesignationManager does not handle the textual typeDesignations
1578
            for (TypeDesignationBase<?> typeDes: designationList) {
1579
            	if (typeDes instanceof TextualTypeDesignation) {
1580
            		typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
1581
            		typeTextDesignations =  typeTextDesignations + "; ";
1582
            	}
1583
            }
1584
            if (typeTextDesignations.equals("; ")) {
1585
            	typeTextDesignations = "";
1586
            }
1587
            if (StringUtils.isNotBlank(typeTextDesignations)) {
1588
            	typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
1589
            }
1590
            String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true):"";
1591

    
1592
            // typeDesignations = typeDesignationString.toString();
1593
            if (StringUtils.isNotBlank(specimenTypeString)) {
1594
                if (!specimenTypeString.endsWith(".")) {
1595
                	specimenTypeString = specimenTypeString + ".";
1596
                }
1597
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
1598

    
1599
            } else {
1600
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
1601
            }
1602
            if (StringUtils.isNotBlank(typeTextDesignations)) {
1603
                if (!typeTextDesignations.endsWith(".")) {
1604
                	typeTextDesignations = typeTextDesignations + ".";
1605
                }
1606
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
1607

    
1608
            } else {
1609
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
1610
            }
1611
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
1612
        } catch (Exception e) {
1613
            e.printStackTrace();
1614
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
1615
                    + cdmBaseStr(group) + ": " + e.getMessage());
1616
        }
1617
    }
1618

    
1619
    private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup) {
1620
        StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
1621

    
1622
        for (TaggedText text : list) {
1623
            if (text != null && text.getText() != null
1624
                    && (text.getText().equals("Type:") || text.getText().equals("NameType:") || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
1625
                // do nothing
1626
            } else if (text.getType().equals(TagEnum.reference)) {
1627
                homotypicalGroupTypeDesignationString.append(text.getText());
1628
            } else if (text.getType().equals(TagEnum.typeDesignation) ) {
1629
                homotypicalGroupTypeDesignationString
1630
                        .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
1631
            } else {
1632
                homotypicalGroupTypeDesignationString.append(text.getText());
1633
            }
1634
        }
1635

    
1636
        String typeDesignations = homotypicalGroupTypeDesignationString.toString();
1637
        typeDesignations = typeDesignations.trim();
1638

    
1639
        typeDesignations += ".";
1640
        typeDesignations = typeDesignations.replace("..", ".");
1641
        typeDesignations = typeDesignations.replace(". .", ".");
1642
        if (typeDesignations.trim().equals(".")) {
1643
            typeDesignations = null;
1644
        }
1645
        return typeDesignations;
1646
    }
1647

    
1648
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
1649
        try {
1650
            String basionymStart = "(";
1651
            String basionymEnd = ") ";
1652
            String exAuthorSeperator = " ex ";
1653
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
1654
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
1655
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
1656
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
1657

    
1658
            String combinationAuthorString = "";
1659
            if (combinationAuthor != null) {
1660
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
1661
                if (combinationAuthor instanceof Team) {
1662
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
1663
                } else {
1664
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
1665
                    combinationAuthorString = createTropicosAuthorString(person);
1666
                }
1667
            }
1668
            String exCombinationAuthorString = "";
1669
            if (exCombinationAuthor != null) {
1670
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
1671
                if (exCombinationAuthor instanceof Team) {
1672
                    exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
1673
                } else {
1674
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
1675
                    exCombinationAuthorString = createTropicosAuthorString(person);
1676
                }
1677
            }
1678

    
1679
            String basionymAuthorString = "";
1680
            if (basionymAuthor != null) {
1681
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
1682
                if (basionymAuthor instanceof Team) {
1683
                    basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
1684
                } else {
1685
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
1686
                    basionymAuthorString = createTropicosAuthorString(person);
1687
                }
1688
            }
1689

    
1690
            String exBasionymAuthorString = "";
1691

    
1692
            if (exBasionymAuthor != null) {
1693
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
1694
                if (exBasionymAuthor instanceof Team) {
1695
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
1696

    
1697
                } else {
1698
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
1699
                    exBasionymAuthorString = createTropicosAuthorString(person);
1700
                }
1701
            }
1702
            String completeAuthorString = name.getNameCache() + " ";
1703

    
1704
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
1705
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
1706
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
1707
                    ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
1708
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
1709
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
1710
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
1711
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
1712
                    ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
1713
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
1714
                    : "";
1715

    
1716
            return completeAuthorString;
1717
        } catch (Exception e) {
1718
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
1719
                    + cdmBaseStr(name) + ": " + e.getMessage());
1720
            return null;
1721
        }
1722
    }
1723

    
1724
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
1725
        String combinationAuthorString;
1726
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
1727
        Team tempTeam = Team.NewInstance();
1728
        for (Person teamMember : team.getTeamMembers()) {
1729
            combinationAuthorString = createTropicosAuthorString(teamMember);
1730
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
1731
            tempTeam.addTeamMember(tempPerson);
1732
        }
1733
        combinationAuthorString = tempTeam.generateTitle();
1734
        return combinationAuthorString;
1735
    }
1736

    
1737
    private String createTropicosAuthorString(Person teamMember) {
1738
        String nomAuthorString = "";
1739
        String[] splittedAuthorString = null;
1740
        if (teamMember == null) {
1741
            return nomAuthorString;
1742
        }
1743

    
1744
        if (teamMember.getGivenName() != null) {
1745
            String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
1746
            splittedAuthorString = givenNameString.split("\\s");
1747
            for (String split : splittedAuthorString) {
1748
                if (!StringUtils.isBlank(split)) {
1749
                    nomAuthorString += split.substring(0, 1);
1750
                    nomAuthorString += ".";
1751
                }
1752
            }
1753
        }
1754
        if (teamMember.getFamilyName() != null) {
1755
            String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
1756
            splittedAuthorString = familyNameString.split("\\s");
1757
            for (String split : splittedAuthorString) {
1758
                nomAuthorString += " " + split;
1759
            }
1760
        }
1761
        if (isBlank(nomAuthorString.trim())) {
1762
            if (teamMember.getTitleCache() != null) {
1763
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
1764
                splittedAuthorString = titleCacheString.split("\\s");
1765
            } else {
1766
                splittedAuthorString = new String[0];
1767
            }
1768

    
1769
            int index = 0;
1770
            for (String split : splittedAuthorString) {
1771
                if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
1772
                    nomAuthorString += split;
1773
                } else {
1774
                    nomAuthorString = nomAuthorString + " " + split;
1775
                }
1776
                index++;
1777
            }
1778
        }
1779
        return nomAuthorString.trim();
1780
    }
1781

    
1782
    private void handleReference(CdmLightExportState state, Reference reference) {
1783
        try {
1784
            state.addReferenceToStore(reference);
1785
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
1786
            reference = HibernateProxyHelper.deproxy(reference, Reference.class);
1787

    
1788
            handleIdentifier(state, reference);
1789
            String[] csvLine = new String[table.getSize()];
1790
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
1791
            // TODO short citations correctly
1792
            String shortCitation = ((DefaultReferenceCacheStrategy) reference.getCacheStrategy())
1793
                    .createShortCitation(reference); // Should be Author(year)
1794
                                                     // like in Taxon.sec
1795
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
1796
            // TODO get preferred title
1797
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
1798
                    ? reference.getTitleCache() : reference.getTitle();
1799
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
1800
                    ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
1801
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
1802
            // TBC
1803
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
1804
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
1805
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
1806
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
1807
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
1808
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
1809
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
1810
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
1811
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
1812
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
1813
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
1814
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
1815

    
1816
            if (reference.getAuthorship() != null) {
1817
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
1818
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
1819
            }
1820

    
1821
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
1822
            if (reference.getInReference() != null
1823
                    && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
1824
                handleReference(state, reference.getInReference());
1825
            }
1826
            if (reference.getInstitution() != null) {
1827
                csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
1828
            }
1829
            if (reference.getLsid() != null) {
1830
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
1831
            }
1832
            if (reference.getSchool() != null) {
1833
                csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
1834
            }
1835
            if (reference.getUri() != null) {
1836
                csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
1837
            }
1838
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
1839

    
1840
            state.getProcessor().put(table, reference, csvLine);
1841

    
1842

    
1843
        } catch (Exception e) {
1844
            state.getResult().addException(e, "An unexpected error occurred when handling reference "
1845
                    + cdmBaseStr(reference) + ": " + e.getMessage());
1846
        }
1847
    }
1848

    
1849
    private String createFullAuthorship(Reference reference) {
1850
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
1851
        String fullAuthorship = "";
1852
        if (authorship == null) {
1853
            return null;
1854
        }
1855
        authorship = HibernateProxyHelper.deproxy(authorship);
1856
        if (authorship instanceof Person) {
1857
            fullAuthorship = ((Person) authorship).getTitleCache();
1858

    
1859
        } else if (authorship instanceof Team) {
1860

    
1861
            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
1862
            int index = 0;
1863

    
1864
            for (Person teamMember : authorTeam.getTeamMembers()) {
1865
                index++;
1866
                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
1867
                fullAuthorship += concat + teamMember.getTitleCache();
1868
            }
1869
            if (StringUtils.isBlank(fullAuthorship)){
1870
                fullAuthorship = authorTeam.getTitleCache();
1871
            }
1872
        }
1873
        return fullAuthorship;
1874
    }
1875

    
1876
    private static String concatString(Team team, List<Person> teamMembers, int i) {
1877
        String concat;
1878
        if (i <= 1) {
1879
            concat = "";
1880
        } else if (i < teamMembers.size() || (team.isHasMoreMembers() && i == teamMembers.size())) {
1881
            concat = STD_TEAM_CONCATINATION;
1882
        } else {
1883
            concat = FINAL_TEAM_CONCATINATION;
1884
        }
1885
        return concat;
1886
    }
1887

    
1888
    /*
1889
     * TypeDesignation table Specimen_Fk EditName_Fk TypeVerbatimCitation
1890
     * TypeCategory TypeDesignatedByString TypeDesignatedByRef_Fk
1891
     */
1892

    
1893
    // private void handleSpecimenTypeDesignations(CdmLightExportState state,
1894
    // TaxonName name){
1895
    // try {
1896
    // Set<SpecimenTypeDesignation> typeDesignations =
1897
    // name.getSpecimenTypeDesignations();
1898
    // CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1899
    // String nameId = getId(state, name);
1900
    // String[] csvLine = new String[table.getSize()];
1901
    // for (SpecimenTypeDesignation specimenType: typeDesignations){
1902
    // csvLine = new String[table.getSize()];
1903
    // DerivedUnit specimen = specimenType.getTypeSpecimen();
1904
    // if (state.getSpecimenFromStore(specimen.getId()) == null){
1905
    // handleSpecimen(state, specimen);
1906
    // }
1907
    // csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
1908
    // specimenType.getTypeSpecimen());
1909
    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
1910
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] =
1911
    // specimenType.getTypeSpecimen().generateTitle();
1912
    // //TODO: add link to existing Vorcabulary
1913
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
1914
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] =
1915
    // specimenType.getCitation().getTitleCache();
1916
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] =
1917
    // getId(state, specimenType.getCitation());
1918
    // }
1919
    // } catch (Exception e) {
1920
    // state.getResult().addException(e, "An unexpected error occurred when
1921
    // handling specimen type designations for " +
1922
    // cdmBaseStr(name) + ": " + e.getMessage());
1923
    // }
1924
    // }
1925

    
1926
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
1927
        try {
1928
            state.addSpecimenToStore(specimen);
1929
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
1930
            String specimenId = getId(state, specimen);
1931
            String[] csvLine = new String[table.getSize()];
1932

    
1933
            /*
1934
             * SpecimenCitation = “El Salvador, Municipio La Libertad, San
1935
             * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
1936
             * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
1937
             * HerbariumCode
1938
             *
1939
             */
1940

    
1941
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
1942
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
1943
            Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
1944
            if (fieldUnits.size() == 1) {
1945
                Iterator<FieldUnit> iterator = fieldUnits.iterator();
1946
                if (iterator.hasNext()){
1947
                    FieldUnit fieldUnit = iterator.next();
1948
                    csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
1949
                }
1950
            }
1951
            if (specimen.isInstanceOf(DerivedUnit.class)){
1952
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
1953
                if (!StringUtils.isBlank(derivedUnit.getBarcode())){
1954
                    csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
1955
                }
1956
                if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
1957
                    csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
1958
                }
1959
                if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
1960
                    csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
1961
                }
1962
            }
1963

    
1964
            csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
1965
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractURIs(state,
1966
                    specimen.getDescriptions(), Feature.IMAGE());
1967
            if (specimen instanceof DerivedUnit) {
1968
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
1969
                if (derivedUnit.getCollection() != null) {
1970
                    csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
1971
                            .getCode();
1972
                }
1973

    
1974
                if (specimen instanceof MediaSpecimen) {
1975
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
1976
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
1977
                    String mediaUris = extractMediaUris(it);
1978
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
1979

    
1980
                }
1981

    
1982
                if (derivedUnit.getDerivedFrom() != null) {
1983
                    for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
1984
                        // TODO: What to do if there are more then one
1985
                        // FieldUnit??
1986
                        if (original instanceof FieldUnit) {
1987
                            FieldUnit fieldUnit = (FieldUnit) original;
1988
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
1989

    
1990
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
1991
                            if (gathering != null) {
1992
                                if (gathering.getLocality() != null) {
1993
                                    csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
1994
                                            .getText();
1995
                                }
1996
                                if (gathering.getCountry() != null) {
1997
                                    csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
1998
                                            .getLabel();
1999
                                }
2000
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2001
                                        state, gathering, fieldUnit);
2002

    
2003
                                if (gathering.getGatheringDate() != null) {
2004
                                    csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2005
                                            .getGatheringDate().toString();
2006
                                }
2007
                                if (!gathering.getCollectingAreas().isEmpty()) {
2008
                                    int index = 0;
2009
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2010
                                    for (NamedArea area : gathering.getCollectingAreas()) {
2011
                                        if (index == 0) {
2012
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2013
                                                    .getLevel().getLabel():"";
2014
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2015
                                        }
2016
                                        if (index == 1) {
2017
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2018
                                                    .getLevel().getLabel():"";
2019
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2020
                                        }
2021
                                        if (index == 2) {
2022
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2023
                                                    .getLevel().getLabel():"";
2024
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2025
                                        }
2026
                                        if (index == 3) {
2027
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2028
                                            break;
2029
                                        }
2030
                                        index++;
2031
                                    }
2032
                                }
2033
                            }
2034
                        }
2035
                    }
2036
                } else {
2037
                    state.getResult().addError("The specimen with uuid " + specimen.getUuid()
2038
                            + " is not an DerivedUnit. Could not be exported.");
2039
                }
2040
            }
2041

    
2042
            state.getProcessor().put(table, specimen, csvLine);
2043
        } catch (Exception e) {
2044
            state.getResult().addException(e, "An unexpected error occurred when handling specimen "
2045
                    + cdmBaseStr(specimen) + ": " + e.getMessage());
2046
        }
2047
    }
2048

    
2049
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
2050

    
2051
        String mediaUriString = "";
2052
        boolean first = true;
2053
        while (it.hasNext()) {
2054
            MediaRepresentation rep = it.next();
2055
            List<MediaRepresentationPart> parts = rep.getParts();
2056
            for (MediaRepresentationPart part : parts) {
2057
                if (first) {
2058
                    if (part.getUri() != null) {
2059
                        mediaUriString += part.getUri().toString();
2060
                        first = false;
2061
                    }
2062
                } else {
2063
                    if (part.getUri() != null) {
2064
                        mediaUriString += ", " + part.getUri().toString();
2065
                    }
2066
                }
2067
            }
2068
        }
2069

    
2070
        return mediaUriString;
2071
    }
2072

    
2073
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2074
        try {
2075
            String collectorString = "";
2076
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2077
            if (gathering.getCollector() != null) {
2078
                if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2079

    
2080
                    Person primaryCollector = fieldUnit.getPrimaryCollector();
2081
                    if (collectorA instanceof Team) {
2082
                        Team collectorTeam = (Team) collectorA;
2083
                        boolean isFirst = true;
2084
                        for (Person member : collectorTeam.getTeamMembers()) {
2085
                            if (!isFirst) {
2086
                                collectorString += "; ";
2087
                            }
2088
                            if (member.equals(primaryCollector)) {
2089
                                // highlight
2090
                                collectorString += "<b>" + member.getTitleCache() + "</b>";
2091
                            } else {
2092
                                collectorString += member.getTitleCache();
2093
                            }
2094
                        }
2095
                    }
2096
                } else {
2097
                    collectorString = collectorA.getTitleCache();
2098
                }
2099
            }
2100
            return collectorString;
2101
        } catch (Exception e) {
2102
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2103
                    + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2104
            return "";
2105
        }
2106
    }
2107

    
2108
    /**
2109
     * Returns a string representation of the {@link CdmBase cdmBase} object for
2110
     * result messages.
2111
     */
2112
    private String cdmBaseStr(CdmBase cdmBase) {
2113
        if (cdmBase == null) {
2114
            return "-no object available-";
2115
        } else {
2116
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2117
        }
2118
    }
2119

    
2120
    @Override
2121
    protected boolean doCheck(CdmLightExportState state) {
2122
        return false;
2123
    }
2124

    
2125
    @Override
2126
    protected boolean isIgnore(CdmLightExportState state) {
2127
        return false;
2128
    }
2129

    
2130
}
(1-1/6)