Project

General

Profile

Download (120 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.TaxonDescription;
60
import eu.etaxonomy.cdm.model.description.TaxonInteraction;
61
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
62
import eu.etaxonomy.cdm.model.description.TextData;
63
import eu.etaxonomy.cdm.model.location.NamedArea;
64
import eu.etaxonomy.cdm.model.media.ExternalLink;
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.NameTypeDesignation;
73
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
74
import eu.etaxonomy.cdm.model.name.Rank;
75
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
76
import eu.etaxonomy.cdm.model.name.TaxonName;
77
import eu.etaxonomy.cdm.model.name.TextualTypeDesignation;
78
import eu.etaxonomy.cdm.model.name.TypeComparator;
79
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
80
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
81
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
82
import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
83
import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
84
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
85
import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
86
import eu.etaxonomy.cdm.model.reference.Reference;
87
import eu.etaxonomy.cdm.model.reference.ReferenceType;
88
import eu.etaxonomy.cdm.model.taxon.Classification;
89
import eu.etaxonomy.cdm.model.taxon.Synonym;
90
import eu.etaxonomy.cdm.model.taxon.Taxon;
91
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
92
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
93
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
94
import eu.etaxonomy.cdm.model.term.DefinedTerm;
95
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
96
import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDtoByRankAndNameComparator;
97
import eu.etaxonomy.cdm.strategy.cache.TagEnum;
98
import eu.etaxonomy.cdm.strategy.cache.TaggedText;
99
import eu.etaxonomy.cdm.strategy.cache.reference.DefaultReferenceCacheStrategy;
100
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
101

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

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

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

    
118
    @Autowired
119
    IEditGeoService geoService;
120

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

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

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

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

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

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

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

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

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

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

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

    
197
        // String sortIndex = StringUtils.isBlank(sort_index)?
198
        // String.valueOf(order.getOrderIndex()): sort_index+ "_"
199
        // +String.valueOf(order.getOrderIndex());
200

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

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

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

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

    
244
    private void handleTaxonNode(CdmLightExportState state, TaxonNode taxonNode) {
245

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

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

    
276
                }
277
                if (root.hasTaxon()) {
278
                    handleTaxon(state, root);
279

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

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

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

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

    
331

    
332
                    for (Taxon tax : taxon.getAllMisappliedNames()) {
333
                        handleProPartePartialMisapplied(state, tax, taxon, false, true, index);
334
                        index++;
335
                    }
336

    
337
                    CdmLightExportTable table = CdmLightExportTable.TAXON;
338
                    String[] csvLine = new String[table.getSize()];
339

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

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

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

    
390
            taxonNode.removeNullValueFromChildren();
391
            // for (TaxonNode child: taxonNode.getChildNodes()){
392
            // handleTaxon(state, child);
393
            // }
394
        } catch (Exception e) {
395
            state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
396
                    + cdmBaseStr(taxonNode.getTaxon()) + ": " + e.getMessage());
397
        }
398
    }
399

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

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

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

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

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

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

    
528
    private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
529
            List<DescriptionElementBase> taxonInteractionsFacts) {
530
        CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
531
        for (DescriptionElementBase element : taxonInteractionsFacts) {
532
            try {
533

    
534
                String[] csvLine = new String[table.getSize()];
535

    
536
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
537
                handleSource(state, element, table);
538
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
539
                csvLine[table.getIndex(CdmLightExportTable.TAXON2_FK)] = getId(state,
540
                        ((TaxonInteraction) element).getTaxon2());
541
                csvLine[table.getIndex(CdmLightExportTable.DESCRIPTION)] = createMultilanguageString(
542
                        ((TaxonInteraction) element).getDescription());
543
                state.getProcessor().put(table, element, csvLine);
544

    
545
            } catch (Exception e) {
546
                state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
547
                        + cdmBaseStr(element) + ": " + e.getMessage());
548
            }
549
        }
550
    }
551

    
552
    private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
553
            DescriptionElementBase element) {
554
        try {
555
            String[] csvLine;
556
            handleSource(state, element, CdmLightExportTable.MEDIA);
557

    
558
            if (element instanceof TextData) {
559
                TextData textData = (TextData) element;
560
                csvLine = new String[table.getSize()];
561
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
562
                if (cdmBase instanceof Taxon) {
563
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
564
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
565
                } else if (cdmBase instanceof TaxonName) {
566
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
567
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
568
                }
569

    
570
                String mediaUris = "";
571
                for (Media media : textData.getMedia()) {
572
                    String mediaString = extractMediaUris(media.getRepresentations().iterator());
573
                    if (!StringUtils.isBlank(mediaString)) {
574
                        mediaUris += mediaString + ";";
575
                    } else {
576
                        state.getResult().addWarning("Empty Media object for " + cdmBase.getUserFriendlyTypeName() + " "
577
                                + cdmBase.getUuid() + " (media: " + media.getUuid() + ")");
578
                    }
579
                }
580
                csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
581

    
582
            }
583
        } catch (Exception e) {
584
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
585
                    + cdmBaseStr(element) + ": " + e.getMessage());
586
        }
587

    
588
    }
589

    
590
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
591
            DescriptionElementBase element) {
592
        try {
593
            String[] csvLine;
594
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
595

    
596
            if (element instanceof TextData) {
597
                TextData textData = (TextData) element;
598
                csvLine = new String[table.getSize()];
599
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
600
                if (cdmBase instanceof Taxon) {
601
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
602
                    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] =
603
                    // "";
604
                } else if (cdmBase instanceof TaxonName) {
605
                    // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] =
606
                    // "";
607
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
608
                }
609
                csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
610

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

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

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

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

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

    
675
                if (element instanceof IndividualsAssociation) {
676

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

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

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

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

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

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

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

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

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

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

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

    
777
    }
778

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

    
828
    }
829

    
830
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
831
            List<DescriptionElementBase> commonNameFacts) {
832
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
833

    
834
        for (DescriptionElementBase element : commonNameFacts) {
835
            try {
836
                if (element instanceof CommonTaxonName) {
837
                    String[] csvLine = new String[table.getSize()];
838
                    CommonTaxonName commonName = (CommonTaxonName) element;
839
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
840
                    handleSource(state, element, table);
841
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
842
                    if (commonName.getName() != null) {
843
                        csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();
844
                    }
845
                    if (commonName.getLanguage() != null) {
846
                        csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();
847
                    }
848
                    if (commonName.getArea() != null) {
849
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();
850
                    }
851
                    state.getProcessor().put(table, commonName, csvLine);
852
                } else {
853
                    state.getResult()
854
                            .addError("The distribution description for the taxon " + taxon.getUuid()
855
                                    + " is not of type distribution. Could not be exported. UUID of the description element: "
856
                                    + element.getUuid());
857
                }
858
            } catch (Exception e) {
859
                state.getResult().addException(e, "An unexpected error occurred when handling single common name "
860
                        + cdmBaseStr(element) + ": " + e.getMessage());
861
            }
862
        }
863
    }
864

    
865
    /**
866
     * @param sec
867
     * @return
868
     */
869
    private String getTitleCache(IIdentifiableEntity identEntity) {
870
        if (identEntity == null) {
871
            return "";
872
        }
873
        // TODO refresh?
874
        return identEntity.getTitleCache();
875
    }
876

    
877
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
878
        if (cdmBase == null) {
879
            return "";
880
        }
881
        // TODO make configurable
882
        return cdmBase.getUuid().toString();
883
    }
884

    
885
    private void handleSynonym(CdmLightExportState state, Synonym synonym, int index) {
886
        try {
887
            if (isUnpublished(state.getConfig(), synonym)) {
888
                return;
889
            }
890
            TaxonName name = synonym.getName();
891
            handleName(state, name);
892

    
893
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
894
            String[] csvLine = new String[table.getSize()];
895

    
896
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, synonym);
897
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, synonym.getAcceptedTaxon());
898
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
899
            if (synonym.getSec() != null && !state.getReferenceStore().contains(synonym.getSec().getUuid())) {
900
                handleReference(state, synonym.getSec());
901
            }
902
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synonym.getSec());
903
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synonym.getSec());
904
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = synonym.isPublish() ? "1" : "0";
905
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = "0";
906
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = "0";
907
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = "0";
908
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
909
            state.getProcessor().put(table, synonym, csvLine);
910
        } catch (Exception e) {
911
            state.getResult().addException(e, "An unexpected error occurred when handling synonym "
912
                    + cdmBaseStr(synonym) + ": " + e.getMessage());
913
        }
914
    }
915

    
916
    /**
917
     * Handles Misapplied names (including pro parte and partial as well as pro
918
     * parte and partial synonyms
919
     *
920
     * @param state
921
     * @param rel
922
     */
923
    private void handleProPartePartialMisapplied(CdmLightExportState state, Taxon taxon, Taxon accepted, boolean isProParte, boolean isMisapplied, int index) {
924
        try {
925
            Taxon ppSyonym = taxon;
926
            if (isUnpublished(state.getConfig(), ppSyonym)) {
927
                return;
928
            }
929
            TaxonName name = ppSyonym.getName();
930
            handleName(state, name);
931

    
932
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
933
            String[] csvLine = new String[table.getSize()];
934

    
935
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, ppSyonym);
936
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, accepted);
937
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
938

    
939
            Reference secRef = ppSyonym.getSec();
940
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
941
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
942
            Set<TaxonRelationship> rels = accepted.getTaxonRelations(ppSyonym);
943
            TaxonRelationship rel = null;
944
            boolean isPartial = false;
945
            if (rels.size() == 1){
946
                rel = rels.iterator().next();
947

    
948
            }else if (rels.size() > 1){
949
                Iterator<TaxonRelationship> iterator = rels.iterator();
950
                while (iterator.hasNext()){
951
                    rel = iterator.next();
952
                    if (isProParte && rel.getType().isAnySynonym()){
953
                        break;
954
                    } else if (isMisapplied && rel.getType().isAnyMisappliedName()){
955
                        break;
956
                    }else{
957
                        rel = null;
958
                    }
959
                }
960
            }
961
            if (rel != null){
962
                Reference synSecRef = rel.getCitation();
963
                csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
964
                csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
965
                isProParte = rel.getType().isProParte();
966
                isPartial = rel.getType().isPartial();
967

    
968
            }else{
969
                state.getResult().addWarning("An unexpected error occurred when handling "
970
                        + "pro parte/partial synonym or misapplied name  " + cdmBaseStr(taxon) );
971
            }
972

    
973
            // pro parte type
974

    
975
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = isProParte ? "1" : "0";
976
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = isPartial ? "1" : "0";
977
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = isMisapplied ? "1" : "0";
978
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
979
            state.getProcessor().put(table, ppSyonym, csvLine);
980
        } catch (Exception e) {
981
            state.getResult().addException(e, "An unexpected error occurred when handling "
982
                    + "pro parte/partial synonym or misapplied name  " + cdmBaseStr(taxon) + ": " + e.getMessage());
983
        }
984

    
985
    }
986

    
987
    private void handleName(CdmLightExportState state, TaxonName name){
988
        handleName(state, name, false);
989
    }
990

    
991
    private void handleName(CdmLightExportState state, TaxonName name, boolean acceptedName) {
992
        if (name == null || state.getNameStore().containsKey(name.getId())) {
993
            return;
994
        }
995
        try {
996
            Rank rank = name.getRank();
997
            CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
998
            name = HibernateProxyHelper.deproxy(name);
999
            state.getNameStore().put(name.getId(), name.getUuid());
1000
            String[] csvLine = new String[table.getSize()];
1001

    
1002
            csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
1003
            if (name.getLsid() != null) {
1004
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
1005
            } else {
1006
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
1007
            }
1008

    
1009
            handleIdentifier(state, name);
1010
            handleDescriptions(state, name);
1011

    
1012
            csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
1013
            if (rank != null) {
1014
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
1015
                if (rank.isInfraGeneric()) {
1016
                    try {
1017
                        csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank()
1018
                                .getInfraGenericMarker();
1019
                    } catch (UnknownCdmTypeException e) {
1020
                        state.getResult().addError("Infrageneric marker expected but not available for rank "
1021
                                + name.getRank().getTitleCache());
1022
                    }
1023
                }
1024
                if (rank.isInfraSpecific()) {
1025
                    csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
1026
                }
1027
            } else {
1028
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
1029
            }
1030
            if (name.isProtectedTitleCache()) {
1031
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
1032
            } else {
1033
                // TODO: adapt the tropicos titlecache creation
1034
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
1035
            }
1036

    
1037

    
1038
            if (!state.getConfig().isAddHTML()) {
1039
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = name.getFullTitleCache();
1040
            } else {
1041
                List<TaggedText> taggedFullTitleCache = name.getTaggedFullTitle();
1042
                String fullTitleWithHtml = createNameWithItalics(taggedFullTitleCache);
1043
                // TODO: adapt the tropicos titlecache creation
1044
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = fullTitleWithHtml.trim();
1045
            }
1046

    
1047
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
1048
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
1049

    
1050
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
1051
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
1052

    
1053
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
1054
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
1055
            if (name.getBasionymAuthorship() != null) {
1056
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
1057
                    handleAuthor(state, name.getBasionymAuthorship());
1058
                }
1059
            }
1060
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state,
1061
                    name.getExBasionymAuthorship());
1062
            if (name.getExBasionymAuthorship() != null) {
1063
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
1064
                    handleAuthor(state, name.getExBasionymAuthorship());
1065
                }
1066

    
1067
            }
1068
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,
1069
                    name.getCombinationAuthorship());
1070
            if (name.getCombinationAuthorship() != null) {
1071
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
1072
                    handleAuthor(state, name.getCombinationAuthorship());
1073
                }
1074
            }
1075
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state,
1076
                    name.getExCombinationAuthorship());
1077
            if (name.getExCombinationAuthorship() != null) {
1078
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
1079
                    handleAuthor(state, name.getExCombinationAuthorship());
1080
                }
1081

    
1082
            }
1083

    
1084
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
1085

    
1086
            Reference nomRef = name.getNomenclaturalReference();
1087

    
1088
            if (nomRef != null) {
1089
                if (!state.getReferenceStore().contains(nomRef.getUuid())) {
1090
                    handleReference(state, nomRef);
1091
                }
1092
                csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
1093
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
1094
                if (nomRef.getVolume() != null) {
1095
                    csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
1096
                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
1097
                }
1098
                if (nomRef.getDatePublished() != null) {
1099
                    csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
1100
                    csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
1101
                    csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = nomRef.getDatePublished()
1102
                            .getVerbatimDate();
1103
                }
1104
                if (name.getNomenclaturalMicroReference() != null) {
1105
                    csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
1106
                }
1107
                nomRef = HibernateProxyHelper.deproxy(nomRef);
1108
                if (nomRef.getInReference() != null) {
1109
                    Reference inReference = nomRef.getInReference();
1110
                    if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null) {
1111
                        csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference
1112
                                .getDatePublishedString();
1113
                        csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished()
1114
                                .getYear();
1115
                    }
1116
                    if (nomRef.getVolume() == null && inReference.getVolume() != null) {
1117
                        csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
1118
                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
1119
                    }
1120
                    if (inReference.getInReference() != null) {
1121
                        inReference = inReference.getInReference();
1122
                    }
1123
                    if (inReference.getAbbrevTitle() == null) {
1124
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1125
                                .Nz(inReference.getTitle());
1126
                    } else {
1127
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1128
                                .Nz(inReference.getAbbrevTitle());
1129
                    }
1130
                    if (inReference.getTitle() == null) {
1131
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils
1132
                                .Nz(inReference.getAbbrevTitle()!= null? inReference.getAbbrevTitle(): inReference.getTitleCache());
1133
                    } else {
1134
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
1135
                    }
1136

    
1137
                    TeamOrPersonBase<?> author = inReference.getAuthorship();
1138
                    if (author != null
1139
                            && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))) {
1140
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1141
                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitle());
1142
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1143
                                .Nz(author.getTitleCache());
1144
                    } else {
1145
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1146
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1147
                    }
1148
                } else {
1149
                    if (nomRef.getAbbrevTitle() == null) {
1150
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1151
                                .Nz(nomRef.getTitle()!= null? nomRef.getTitle():nomRef.getAbbrevTitleCache());
1152
                    } else {
1153
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1154
                                .Nz(nomRef.getAbbrevTitle());
1155
                    }
1156
                    if (nomRef.getTitle() == null) {
1157
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] =  CdmUtils
1158
                                .Nz(nomRef.getAbbrevTitle()!= null? nomRef.getAbbrevTitle(): nomRef.getTitleCache());
1159
                    } else {
1160
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
1161
                    }
1162
                    TeamOrPersonBase<?> author = nomRef.getAuthorship();
1163
                    if (author != null) {
1164
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1165
                                ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitle());
1166
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1167
                                .Nz(author.getTitleCache());
1168
                    } else {
1169
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1170
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1171
                    }
1172

    
1173
                }
1174
            } else {
1175
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
1176
            }
1177

    
1178
            /*
1179
             * Collation
1180
             *
1181
             * Detail
1182
             *
1183
             * TitlePageYear
1184
             */
1185
            String protologueUriString = extractProtologueURIs(state, name);
1186

    
1187
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
1188
            Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1189
            List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1190
            for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1191
                if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1192

    
1193
                    if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1194
                        Set<IdentifiableSource> sources =  typeDesignation.getSources();
1195
                        boolean isProtologue = false;
1196
                        if (sources != null && !sources.isEmpty()){
1197
                            IdentifiableSource source = sources.iterator().next();
1198
                            if (name.getNomenclaturalReference() != null){
1199
                                isProtologue = source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid());
1200
                            }
1201
                        }
1202
                        if (isProtologue){
1203
                            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_TYPE_STATEMENT)] = ((TextualTypeDesignation) typeDesignation)
1204
                                    .getPreferredText(Language.DEFAULT());
1205
                        }else{
1206
                            textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1207
                        }
1208

    
1209
                    } else {
1210
                        textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1211
                    }
1212
                } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1213

    
1214
                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class));
1215

    
1216
                }else if (typeDesignation instanceof NameTypeDesignation){
1217
                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
1218
                }
1219
            }
1220
            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
1221

    
1222
//            String typeDesignationString = createTypeDesignationString(manager.toTaggedText(false, true, true), false, name.isSpecies() || name.isInfraSpecific());
1223
//            String test = manager.print(false, false, false);
1224

    
1225
            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false);
1226

    
1227
            StringBuilder stringbuilder = new StringBuilder();
1228
            int i = 1;
1229
            for (TextualTypeDesignation typeDesignation : textualTypeDesignations) {
1230
                stringbuilder.append(typeDesignation.getPreferredText(Language.DEFAULT()));
1231
                if (typeDesignation.getSources() != null && !typeDesignation.getSources().isEmpty() ){
1232
                    stringbuilder.append( " [");
1233
                    int index = 1;
1234
                    for (IdentifiableSource source: typeDesignation.getSources()){
1235
                        if (source.getCitation() != null){
1236
                            stringbuilder.append(((DefaultReferenceCacheStrategy)source.getCitation().getCacheStrategy()).getCitation(source.getCitation()));
1237
                        }
1238
                        if (index < typeDesignation.getSources().size()) {
1239
                            stringbuilder.append( ", ");
1240
                        }
1241
                        index++;
1242
                    }
1243
                    stringbuilder.append( "]");
1244
                }
1245
                if (i < textualTypeDesignations.size()) {
1246
                    stringbuilder.append( "; ");
1247
                } else {
1248
                    stringbuilder.append(".");
1249
                }
1250
                i++;
1251
            }
1252
            csvLine[table.getIndex(CdmLightExportTable.TYPE_STATEMENT)] = stringbuilder.toString();
1253

    
1254

    
1255
            if (name.getStatus() == null || name.getStatus().isEmpty()) {
1256
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
1257
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
1258
            } else {
1259

    
1260
                String statusStringAbbrev = extractStatusString(state, name, true);
1261
                String statusString = extractStatusString(state, name, false);
1262

    
1263
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
1264
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
1265
            }
1266

    
1267
            HomotypicalGroup group = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
1268

    
1269
//            if (!state.containsHomotypicalGroupFromStore(group.getUuid())) {
1270
//                if (acceptedName){
1271
//                    handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
1272
//                }else{
1273
//                    handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
1274
//                }
1275
//            }
1276
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
1277
            List<TaxonName> typifiedNames = new ArrayList<>();
1278
            typifiedNames.addAll(group.getTypifiedNames());
1279
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1280
            Integer seqNumber = typifiedNames.indexOf(name);
1281
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1282
            state.getProcessor().put(table, name, csvLine);
1283
            handleNameRelationships(state, name);
1284

    
1285
        } catch (Exception e) {
1286
            state.getResult().addException(e,
1287
                    "An unexpected error occurred when handling synonym " + cdmBaseStr(name) + ": " + e.getMessage());
1288

    
1289
            e.printStackTrace();
1290
        }
1291
    }
1292

    
1293
    private String createNameWithItalics(List<TaggedText> taggedName) {
1294

    
1295
        String fullTitleWithHtml = "";
1296
        for (TaggedText taggedText: taggedName){
1297
            if (taggedText.getType().equals(TagEnum.name)){
1298
                fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1299
            }else if (taggedText.getType().equals(TagEnum.separator)){
1300
                fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1301
            }else{
1302
                fullTitleWithHtml += taggedText.getText() + " ";
1303
            }
1304
        }
1305
        return fullTitleWithHtml;
1306
    }
1307

    
1308
    private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1309
        Set<NameRelationship> rels = name.getRelationsFromThisName();
1310
        CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1311
        String[] csvLine = new String[table.getSize()];
1312

    
1313
        for (NameRelationship rel : rels) {
1314
            NameRelationshipType type = rel.getType();
1315
            TaxonName name2 = rel.getToName();
1316
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1317
            if (!state.getNameStore().containsKey(name2.getId())) {
1318
                handleName(state, name2);
1319
            }
1320

    
1321
            csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1322
            csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1323
            csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1324
            state.getProcessor().put(table, name, csvLine);
1325
        }
1326

    
1327
        rels = name.getRelationsToThisName();
1328

    
1329
        csvLine = new String[table.getSize()];
1330

    
1331
        for (NameRelationship rel : rels) {
1332
            NameRelationshipType type = rel.getType();
1333
            TaxonName name2 = rel.getFromName();
1334
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1335
            if (!state.getNameStore().containsKey(name2.getId())) {
1336
                handleName(state, name2);
1337
            }
1338

    
1339

    
1340
        }
1341
    }
1342

    
1343
    private String createCollatation(TaxonName name) {
1344
        String collation = "";
1345
        if (name.getNomenclaturalReference() != null) {
1346
            Reference ref = name.getNomenclaturalReference();
1347
            collation = getVolume(ref);
1348
        }
1349
        if (name.getNomenclaturalMicroReference() != null) {
1350
            if (!StringUtils.isBlank(collation)) {
1351
                collation += ":";
1352
            }
1353
            collation += name.getNomenclaturalMicroReference();
1354
        }
1355

    
1356
        return collation;
1357
    }
1358

    
1359
    private String getVolume(Reference reference) {
1360
        if (reference.getVolume() != null) {
1361
            return reference.getVolume();
1362
        } else if (reference.getInReference() != null) {
1363
            if (reference.getInReference().getVolume() != null) {
1364
                return reference.getInReference().getVolume();
1365
            }
1366
        }
1367
        return null;
1368
    }
1369

    
1370
    private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1371
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1372
        String[] csvLine;
1373
        try {
1374
            if (cdmBase instanceof TaxonName){
1375
                TaxonName name = (TaxonName)cdmBase;
1376

    
1377
                try{
1378
                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1379
                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1380
                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1381
                    if (!IPNIidentifiers.isEmpty()) {
1382
                        csvLine = new String[table.getSize()];
1383
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1384
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1385
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1386
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1387
                                IPNIidentifiers);
1388
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1389
                    }
1390
                    if (!tropicosIdentifiers.isEmpty()) {
1391
                        csvLine = new String[table.getSize()];
1392
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1393
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1394
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = name.getUuid() + ", " + IPNI_NAME_IDENTIFIER;
1395
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1396
                                tropicosIdentifiers);
1397
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1398
                    }
1399
                    if (!WFOIdentifiers.isEmpty()) {
1400
                        csvLine = new String[table.getSize()];
1401
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1402
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1403
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1404
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1405
                                WFOIdentifiers);
1406
                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1407
                    }
1408
                }catch(Exception e){
1409
                    state.getResult().addWarning("Please check the identifiers for "
1410
                            + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1411

    
1412

    
1413
                }
1414
            }else{
1415
                if (cdmBase instanceof IdentifiableEntity){
1416
                    IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1417
                    List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1418
                    String tableName = null;
1419
                    if (cdmBase instanceof Reference){
1420
                        tableName = "Reference";
1421
                    }else if (cdmBase instanceof SpecimenOrObservationBase){
1422
                        tableName = "Specimen";
1423
                    }else if (cdmBase instanceof Taxon){
1424
                        tableName = "Taxon";
1425
                    }else if (cdmBase instanceof Synonym){
1426
                        tableName = "Synonym";
1427
                    }else if (cdmBase instanceof TeamOrPersonBase){
1428
                        tableName = "PersonOrTeam";
1429
                    }
1430

    
1431
                    for (Identifier<?> identifier: identifiers){
1432
                        if (identifier.getType() == null && identifier.getIdentifier() == null){
1433
                            state.getResult().addWarning("Please check the identifiers for "
1434
                                    + cdmBaseStr(cdmBase) + " there is an empty identifier");
1435
                            continue;
1436
                        }
1437

    
1438
                        csvLine = new String[table.getSize()];
1439
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1440

    
1441
                        if (tableName != null){
1442
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1443
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1444
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1445
                            state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1446
                        }
1447
                    }
1448
                    if (cdmBase instanceof Reference ){
1449
                        Reference ref = (Reference)cdmBase;
1450
                        if (ref.getDoi() != null){
1451
                            csvLine = new String[table.getSize()];
1452
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1453
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1454
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1455
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1456
                            state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1457
                        }
1458
                    }
1459

    
1460
                    if (cdmBase instanceof TeamOrPersonBase){
1461
                        TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1462
                        if (person instanceof Person &&  ((Person)person).getOrcid() != null){
1463
                            csvLine = new String[table.getSize()];
1464
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1465
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1466
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1467
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]=  ((Person)person).getOrcid().asURI();
1468
                            state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1469
                        }
1470
                    }
1471
                }
1472
            }
1473
        } catch (Exception e) {
1474
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1475
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1476
            e.printStackTrace();
1477
        }
1478
    }
1479

    
1480
    private String extractIdentifier(Set<String> identifierSet) {
1481

    
1482
        String identifierString = "";
1483
        for (String identifier : identifierSet) {
1484
            if (!StringUtils.isBlank(identifierString)) {
1485
                identifierString += ", ";
1486
            }
1487
            identifierString += identifier;
1488
        }
1489
        return identifierString;
1490
    }
1491

    
1492
    private String extractProtologueURIs(CdmLightExportState state, TaxonName name) {
1493
        if (name.getNomenclaturalSource() != null){
1494
            Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1495
            return extractLinkUris(links.iterator());
1496
        }else{
1497
            return null;
1498
        }
1499
    }
1500

    
1501
    private String extractMediaURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1502
            Feature feature) {
1503

    
1504
        String mediaUriString = "";
1505
        Set<DescriptionElementBase> elements = new HashSet<>();
1506
        for (DescriptionBase<?> description : descriptionsSet) {
1507
            try {
1508
                if (!description.getElements().isEmpty()) {
1509
                    elements = description.getElements();
1510

    
1511
                    for (DescriptionElementBase element : elements) {
1512
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1513
                        if (entityFeature.equals(feature)) {
1514
                            if (!element.getMedia().isEmpty()) {
1515
                                List<Media> media = element.getMedia();
1516
                                for (Media mediaElement : media) {
1517
                                    Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1518
                                    mediaUriString = extractMediaUris(it);
1519
                                }
1520
                            }
1521
                        }
1522
                    }
1523
                }
1524
            } catch (Exception e) {
1525
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1526
                        + cdmBaseStr(description) + ": " + e.getMessage());
1527
            }
1528
        }
1529
        return mediaUriString;
1530
    }
1531

    
1532
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1533
        try {
1534
            if (state.getAuthorFromStore(author.getId()) != null) {
1535
                return;
1536
            }
1537
            state.addAuthorToStore(author);
1538
            handleIdentifier(state, author);
1539
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1540
            String[] csvLine = new String[table.getSize()];
1541
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1542
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
1543
            String[] csvLineMember = new String[table.getSize()];
1544
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1545
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1546
                    ? author.getTitleCache() : author.getNomenclaturalTitle();
1547
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1548
            author = HibernateProxyHelper.deproxy(author);
1549
            if (author instanceof Person) {
1550
                Person authorPerson = (Person) author;
1551
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1552
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1553
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1554
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1555
            } else {
1556
                // create an entry in rel table and all members in author table,
1557
                // check whether the team members already in author table
1558

    
1559
                Team authorTeam = (Team) author;
1560
                int index = 0;
1561
                for (Person member : authorTeam.getTeamMembers()) {
1562
                    csvLineRel = new String[tableAuthorRel.getSize()];
1563
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1564
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1565
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1566
                            .valueOf(index);
1567
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1568

    
1569
                    if (state.getAuthorFromStore(member.getId()) == null) {
1570
                        state.addAuthorToStore(member);
1571
                        csvLineMember = new String[table.getSize()];
1572
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1573
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1574
                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitle();
1575
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1576
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1577
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1578
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1579
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1580
                        state.getProcessor().put(table, member, csvLineMember);
1581
                    }
1582
                    index++;
1583
                }
1584
            }
1585
            state.getProcessor().put(table, author, csvLine);
1586
        } catch (Exception e) {
1587
            state.getResult().addException(e,
1588
                    "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1589
        }
1590
    }
1591

    
1592
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1593
        try {
1594
            Set<NomenclaturalStatus> status = name.getStatus();
1595
            if (status.isEmpty()) {
1596
                return "";
1597
            }
1598
            String statusString = "";
1599
            for (NomenclaturalStatus nameStatus : status) {
1600
                if (nameStatus != null) {
1601
                    if (abbrev) {
1602
                        if (nameStatus.getType() != null) {
1603
                            statusString += nameStatus.getType().getIdInVocabulary();
1604
                        }
1605
                    } else {
1606
                        if (nameStatus.getType() != null) {
1607
                            statusString += nameStatus.getType().getTitleCache();
1608
                        }
1609
                    }
1610
                    if (!abbrev) {
1611

    
1612
                        if (nameStatus.getRuleConsidered() != null
1613
                                && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1614
                            statusString += " " + nameStatus.getRuleConsidered();
1615
                        }
1616
                        if (nameStatus.getCitation() != null) {
1617
                            statusString += " " + nameStatus.getCitation().getTitleCache();
1618
                        }
1619
                        if (nameStatus.getCitationMicroReference() != null
1620
                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1621
                            statusString += " " + nameStatus.getCitationMicroReference();
1622
                        }
1623
                    }
1624
                    statusString += " ";
1625
                }
1626
            }
1627
            return statusString;
1628
        } catch (Exception e) {
1629
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1630
                    + cdmBaseStr(name) + ": " + e.getMessage());
1631
            return "";
1632
        }
1633
    }
1634

    
1635
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, int sortIndex) {
1636
        try {
1637
            state.addHomotypicalGroupToStore(group);
1638
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1639
            String[] csvLine = new String[table.getSize()];
1640
            csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(sortIndex);
1641
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1642
            List<TaxonName> typifiedNames = new ArrayList<>();
1643
//            typifiedNames.addAll(group.getTypifiedNames());
1644
            group.getTypifiedNames().stream().forEach(name -> typifiedNames.add(HibernateProxyHelper.deproxy(name, TaxonName.class)));
1645
            TaxonName firstname = null;
1646
            for (TaxonName name: typifiedNames){
1647
                Iterator<Taxon> taxa = name.getTaxa().iterator();
1648
                while(taxa.hasNext()){
1649
                    Taxon taxon = taxa.next();
1650
                    if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1651
                        firstname = name;
1652
                        break;
1653
                    }
1654
                }
1655
            }
1656

    
1657
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1658
            String typifiedNamesString = "";
1659
            String typifiedNamesWithSecString = "";
1660
            String typifiedNamesWithoutAccepted = "";
1661
            String typifiedNamesWithoutAcceptedWithSec = "";
1662
            int index = 0;
1663
            for (TaxonName name : typifiedNames) {
1664
                // Concatenated output string for homotypic group (names and
1665
                // citations) + status + some name relations (e.g. “non”)
1666
                // TODO: nameRelations, which and how to display
1667
                Set<TaxonBase> taxonBases = name.getTaxonBases();
1668
                TaxonBase<?> taxonBase;
1669

    
1670
                String sec = "";
1671
                String nameString = name.getFullTitleCache();
1672

    
1673
                if (state.getConfig().isAddHTML()){
1674
                    nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1675
                }
1676

    
1677
                if (index > 0){
1678
                    boolean isInvalid = false;
1679

    
1680
                    for (NomenclaturalStatus status: name.getStatus()){
1681
                        if (status != null && status.getType() != null && status.getType().isInvalidType()){
1682
                            isInvalid = true;
1683
                            break;
1684
                        }
1685
                    }
1686
                    if (isInvalid){
1687
                        nameString = "\u2212 " + nameString;
1688
                    }else{
1689
                        nameString = "\u2261 " + nameString;
1690
                    }
1691
                }
1692
                boolean isAccepted = false;
1693

    
1694
                if (taxonBases.size() == 1){
1695
                     taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
1696
                     Reference secRef = taxonBase.getSec();
1697
                     if (secRef != null){
1698
                         sec = ((DefaultReferenceCacheStrategy) secRef.getCacheStrategy())
1699
                             .createShortCitation(secRef);
1700
                     }
1701
                     if (taxonBase instanceof Synonym){
1702
                         if (StringUtils.isNotBlank(sec)){
1703
                             sec = " syn. sec. " + sec;
1704
                         }else {
1705
                             sec = "";
1706
                         }
1707
                         typifiedNamesWithoutAccepted += nameString ;
1708
                         typifiedNamesWithoutAcceptedWithSec += nameString + sec ;
1709
                     }else{
1710
                         sec = "";
1711
                         if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
1712
                             isAccepted = true;
1713
                         }
1714

    
1715
                     }
1716

    
1717
                }else{
1718
                    //there are names used more than once?
1719
                    for (TaxonBase<?> tb: taxonBases){
1720
                        Reference secRef = tb.getSec();
1721
                        if (secRef != null){
1722
                            sec = ((DefaultReferenceCacheStrategy) secRef.getCacheStrategy())
1723
                                .createShortCitation(secRef);
1724
                        }
1725
                        if (tb instanceof Synonym){
1726
                            if (StringUtils.isNotBlank(sec)){
1727
                                sec = " syn. sec. " + sec;
1728
                            }else {
1729
                                sec = "";
1730
                            }
1731
                            break;
1732
                        }else{
1733
                            sec = "";
1734
                            if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
1735
                                isAccepted = true;
1736
                                break;
1737
                            }
1738

    
1739
                        }
1740
                    }
1741
                    if (!isAccepted){
1742
                        typifiedNamesWithoutAccepted += nameString + "; ";
1743
                        typifiedNamesWithoutAcceptedWithSec += nameString + sec + "; ";
1744
                    }
1745
                }
1746
                typifiedNamesString += nameString ;
1747
                typifiedNamesWithSecString += nameString + sec;
1748

    
1749

    
1750
                if (typifiedNamesString != null) {
1751
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
1752
                } else {
1753
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
1754
                }
1755

    
1756

    
1757
                if (typifiedNamesWithSecString != null) {
1758
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
1759
                } else {
1760
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = "";
1761
                }
1762

    
1763
                if (typifiedNamesWithoutAccepted != null && firstname != null) {
1764
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
1765
                } else {
1766
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = "";
1767
                }
1768

    
1769
                if (typifiedNamesWithoutAcceptedWithSec != null && firstname != null) {
1770
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = typifiedNamesWithoutAcceptedWithSec.trim();
1771
                } else {
1772
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = "";
1773
                }
1774
                index++;
1775
            }
1776

    
1777
            Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
1778
            List<TypeDesignationBase<?>> designationList = new ArrayList<>();
1779
            designationList.addAll(typeDesigantionSet);
1780
            Collections.sort(designationList, new TypeComparator());
1781

    
1782
            List<TaggedText> list = new ArrayList<>();
1783
            if (!designationList.isEmpty()) {
1784
                TypeDesignationSetManager manager = new TypeDesignationSetManager(group);
1785
                list.addAll(manager.toTaggedText(true, false, false));
1786
            }
1787
            String typeTextDesignations = "";
1788
            //The typeDesignationManager does not handle the textual typeDesignations
1789
            for (TypeDesignationBase<?> typeDes: designationList) {
1790
            	if (typeDes instanceof TextualTypeDesignation) {
1791
            		typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
1792
            		typeTextDesignations =  typeTextDesignations + "; ";
1793
            	}
1794
            }
1795
            if (typeTextDesignations.equals("; ")) {
1796
            	typeTextDesignations = "";
1797
            }
1798
            if (StringUtils.isNotBlank(typeTextDesignations)) {
1799
            	typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
1800
            }
1801
            String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
1802

    
1803
            // typeDesignations = typeDesignationString.toString();
1804
            if (StringUtils.isNotBlank(specimenTypeString)) {
1805
                if (!specimenTypeString.endsWith(".")) {
1806
                	specimenTypeString = specimenTypeString + ".";
1807
                }
1808
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
1809

    
1810
            } else {
1811
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
1812
            }
1813
            if (StringUtils.isNotBlank(typeTextDesignations)) {
1814
                if (!typeTextDesignations.endsWith(".")) {
1815
                	typeTextDesignations = typeTextDesignations + ".";
1816
                }
1817
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
1818

    
1819
            } else {
1820
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
1821
            }
1822
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
1823
        } catch (Exception e) {
1824
            e.printStackTrace();
1825
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
1826
                    + cdmBaseStr(group) + ": " + e.getMessage());
1827
        }
1828
    }
1829

    
1830
    private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup, boolean isSpecimenTypeDesignation) {
1831
        StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
1832

    
1833
        for (TaggedText text : list) {
1834
            if (text != null && text.getText() != null
1835
                    && (text.getText().equals("Type:") || text.getText().equals("NameType:") || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
1836
                // do nothing
1837
            } else if (text.getType().equals(TagEnum.reference)) {
1838
                homotypicalGroupTypeDesignationString.append(text.getText());
1839
            } else if (text.getType().equals(TagEnum.typeDesignation) ) {
1840
                if(isSpecimenTypeDesignation){
1841
                    homotypicalGroupTypeDesignationString
1842
                        .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
1843
                }else{
1844
                    homotypicalGroupTypeDesignationString
1845
                        .append(text.getText());
1846
                }
1847

    
1848
            } else {
1849
                homotypicalGroupTypeDesignationString.append(text.getText());
1850
            }
1851
        }
1852

    
1853
        String typeDesignations = homotypicalGroupTypeDesignationString.toString();
1854
        typeDesignations = typeDesignations.trim();
1855

    
1856
        if (typeDesignations.endsWith(";")){
1857
            typeDesignations = typeDesignations.substring(0, typeDesignations.length()-1);
1858
        }
1859
        typeDesignations += ".";
1860
        typeDesignations = typeDesignations.replace("..", ".");
1861
        typeDesignations = typeDesignations.replace(". .", ".");
1862

    
1863
        if (typeDesignations.trim().equals(".")) {
1864
            typeDesignations = null;
1865
        }
1866

    
1867
        return typeDesignations;
1868
    }
1869

    
1870
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
1871
        try {
1872
            String basionymStart = "(";
1873
            String basionymEnd = ") ";
1874
            String exAuthorSeperator = " ex ";
1875
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
1876
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
1877
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
1878
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
1879

    
1880
            String combinationAuthorString = "";
1881
            if (combinationAuthor != null) {
1882
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
1883
                if (combinationAuthor instanceof Team) {
1884
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
1885
                } else {
1886
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
1887
                    combinationAuthorString = createTropicosAuthorString(person);
1888
                }
1889
            }
1890
            String exCombinationAuthorString = "";
1891
            if (exCombinationAuthor != null) {
1892
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
1893
                if (exCombinationAuthor instanceof Team) {
1894
                    exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
1895
                } else {
1896
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
1897
                    exCombinationAuthorString = createTropicosAuthorString(person);
1898
                }
1899
            }
1900

    
1901
            String basionymAuthorString = "";
1902
            if (basionymAuthor != null) {
1903
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
1904
                if (basionymAuthor instanceof Team) {
1905
                    basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
1906
                } else {
1907
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
1908
                    basionymAuthorString = createTropicosAuthorString(person);
1909
                }
1910
            }
1911

    
1912
            String exBasionymAuthorString = "";
1913

    
1914
            if (exBasionymAuthor != null) {
1915
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
1916
                if (exBasionymAuthor instanceof Team) {
1917
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
1918

    
1919
                } else {
1920
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
1921
                    exBasionymAuthorString = createTropicosAuthorString(person);
1922
                }
1923
            }
1924
            String completeAuthorString = name.getNameCache() + " ";
1925

    
1926
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
1927
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
1928
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
1929
                    ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
1930
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
1931
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
1932
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
1933
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
1934
                    ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
1935
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
1936
                    : "";
1937

    
1938
            return completeAuthorString;
1939
        } catch (Exception e) {
1940
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
1941
                    + cdmBaseStr(name) + ": " + e.getMessage());
1942
            return null;
1943
        }
1944
    }
1945

    
1946
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
1947
        String combinationAuthorString;
1948
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
1949
        Team tempTeam = Team.NewInstance();
1950
        for (Person teamMember : team.getTeamMembers()) {
1951
            combinationAuthorString = createTropicosAuthorString(teamMember);
1952
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
1953
            tempTeam.addTeamMember(tempPerson);
1954
        }
1955
        combinationAuthorString = tempTeam.generateTitle();
1956
        return combinationAuthorString;
1957
    }
1958

    
1959
    private String createTropicosAuthorString(Person teamMember) {
1960
        String nomAuthorString = "";
1961
        String[] splittedAuthorString = null;
1962
        if (teamMember == null) {
1963
            return nomAuthorString;
1964
        }
1965

    
1966
        if (teamMember.getGivenName() != null) {
1967
            String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
1968
            splittedAuthorString = givenNameString.split("\\s");
1969
            for (String split : splittedAuthorString) {
1970
                if (!StringUtils.isBlank(split)) {
1971
                    nomAuthorString += split.substring(0, 1);
1972
                    nomAuthorString += ".";
1973
                }
1974
            }
1975
        }
1976
        if (teamMember.getFamilyName() != null) {
1977
            String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
1978
            splittedAuthorString = familyNameString.split("\\s");
1979
            for (String split : splittedAuthorString) {
1980
                nomAuthorString += " " + split;
1981
            }
1982
        }
1983
        if (isBlank(nomAuthorString.trim())) {
1984
            if (teamMember.getTitleCache() != null) {
1985
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
1986
                splittedAuthorString = titleCacheString.split("\\s");
1987
            } else {
1988
                splittedAuthorString = new String[0];
1989
            }
1990

    
1991
            int index = 0;
1992
            for (String split : splittedAuthorString) {
1993
                if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
1994
                    nomAuthorString += split;
1995
                } else {
1996
                    nomAuthorString = nomAuthorString + " " + split;
1997
                }
1998
                index++;
1999
            }
2000
        }
2001
        return nomAuthorString.trim();
2002
    }
2003

    
2004
    private void handleReference(CdmLightExportState state, Reference reference) {
2005
        try {
2006
            state.addReferenceToStore(reference);
2007
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
2008
            reference = HibernateProxyHelper.deproxy(reference);
2009

    
2010
            handleIdentifier(state, reference);
2011
            String[] csvLine = new String[table.getSize()];
2012
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
2013
            // TODO short citations correctly
2014
            String shortCitation = ((DefaultReferenceCacheStrategy) reference.getCacheStrategy())
2015
                    .createShortCitation(reference); // Should be Author(year)
2016
                                                     // like in Taxon.sec
2017
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
2018
            // TODO get preferred title
2019
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
2020
                    ? reference.getTitleCache() : reference.getTitle();
2021
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
2022
                    ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
2023
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
2024
            // TBC
2025
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
2026
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
2027
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
2028
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
2029
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
2030
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
2031
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
2032
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
2033
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
2034
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
2035
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
2036
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
2037

    
2038
            if (reference.getAuthorship() != null) {
2039
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
2040
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
2041
            }
2042

    
2043
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
2044
            if (reference.getInReference() != null
2045
                    && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
2046
                handleReference(state, reference.getInReference());
2047
            }
2048
            if (reference.getInstitution() != null) {
2049
                csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
2050
            }
2051
            if (reference.getLsid() != null) {
2052
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
2053
            }
2054
            if (reference.getSchool() != null) {
2055
                csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
2056
            }
2057
            if (reference.getUri() != null) {
2058
                csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
2059
            }
2060
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
2061

    
2062
            state.getProcessor().put(table, reference, csvLine);
2063
        } catch (Exception e) {
2064
            state.getResult().addException(e, "An unexpected error occurred when handling reference "
2065
                    + cdmBaseStr(reference) + ": " + e.getMessage());
2066
        }
2067
    }
2068

    
2069
    private String createFullAuthorship(Reference reference) {
2070
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
2071
        String fullAuthorship = "";
2072
        if (authorship == null) {
2073
            return null;
2074
        }
2075
        authorship = HibernateProxyHelper.deproxy(authorship);
2076
        if (authorship instanceof Person) {
2077
            fullAuthorship = ((Person) authorship).getTitleCache();
2078

    
2079
        } else if (authorship instanceof Team) {
2080

    
2081
            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
2082
            int index = 0;
2083

    
2084
            for (Person teamMember : authorTeam.getTeamMembers()) {
2085
                index++;
2086
                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
2087
                fullAuthorship += concat + teamMember.getTitleCache();
2088
            }
2089
            if (StringUtils.isBlank(fullAuthorship)){
2090
                fullAuthorship = authorTeam.getTitleCache();
2091
            }
2092
        }
2093
        return fullAuthorship;
2094
    }
2095

    
2096
    private static String concatString(Team team, List<Person> teamMembers, int i) {
2097
        String concat;
2098
        if (i <= 1) {
2099
            concat = "";
2100
        } else if (i < teamMembers.size() || (team.isHasMoreMembers() && i == teamMembers.size())) {
2101
            concat = STD_TEAM_CONCATINATION;
2102
        } else {
2103
            concat = FINAL_TEAM_CONCATINATION;
2104
        }
2105
        return concat;
2106
    }
2107

    
2108
    /*
2109
     * TypeDesignation table Specimen_Fk EditName_Fk TypeVerbatimCitation
2110
     * TypeCategory TypeDesignatedByString TypeDesignatedByRef_Fk
2111
     */
2112

    
2113
    // private void handleSpecimenTypeDesignations(CdmLightExportState state,
2114
    // TaxonName name){
2115
    // try {
2116
    // Set<SpecimenTypeDesignation> typeDesignations =
2117
    // name.getSpecimenTypeDesignations();
2118
    // CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
2119
    // String nameId = getId(state, name);
2120
    // String[] csvLine = new String[table.getSize()];
2121
    // for (SpecimenTypeDesignation specimenType: typeDesignations){
2122
    // csvLine = new String[table.getSize()];
2123
    // DerivedUnit specimen = specimenType.getTypeSpecimen();
2124
    // if (state.getSpecimenFromStore(specimen.getId()) == null){
2125
    // handleSpecimen(state, specimen);
2126
    // }
2127
    // csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
2128
    // specimenType.getTypeSpecimen());
2129
    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
2130
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] =
2131
    // specimenType.getTypeSpecimen().generateTitle();
2132
    // //TODO: add link to existing Vorcabulary
2133
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
2134
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] =
2135
    // specimenType.getCitation().getTitleCache();
2136
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] =
2137
    // getId(state, specimenType.getCitation());
2138
    // }
2139
    // } catch (Exception e) {
2140
    // state.getResult().addException(e, "An unexpected error occurred when
2141
    // handling specimen type designations for " +
2142
    // cdmBaseStr(name) + ": " + e.getMessage());
2143
    // }
2144
    // }
2145

    
2146
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
2147
        try {
2148
            state.addSpecimenToStore(specimen);
2149
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
2150
            String specimenId = getId(state, specimen);
2151
            String[] csvLine = new String[table.getSize()];
2152

    
2153
            /*
2154
             * SpecimenCitation = “El Salvador, Municipio La Libertad, San
2155
             * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
2156
             * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
2157
             * HerbariumCode
2158
             *
2159
             */
2160

    
2161
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
2162
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
2163
            Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
2164
            if (fieldUnits.size() == 1) {
2165
                Iterator<FieldUnit> iterator = fieldUnits.iterator();
2166
                if (iterator.hasNext()){
2167
                    FieldUnit fieldUnit = iterator.next();
2168
                    csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
2169
                }
2170
            }
2171
            if (specimen.isInstanceOf(DerivedUnit.class)){
2172
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
2173
                if (!StringUtils.isBlank(derivedUnit.getBarcode())){
2174
                    csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
2175
                }
2176
                if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
2177
                    csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
2178
                }
2179
                if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
2180
                    csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
2181
                }
2182
            }
2183

    
2184
            csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
2185
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
2186
                    specimen.getDescriptions(), Feature.IMAGE());
2187
            if (specimen instanceof DerivedUnit) {
2188
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
2189
                if (derivedUnit.getCollection() != null) {
2190
                    csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
2191
                            .getCode();
2192
                }
2193

    
2194
                if (specimen instanceof MediaSpecimen) {
2195
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
2196
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
2197
                    String mediaUris = extractMediaUris(it);
2198
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
2199

    
2200
                }
2201

    
2202
                if (derivedUnit.getDerivedFrom() != null) {
2203
                    for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
2204
                        // TODO: What to do if there are more then one
2205
                        // FieldUnit??
2206
                        if (original instanceof FieldUnit) {
2207
                            FieldUnit fieldUnit = (FieldUnit) original;
2208
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
2209

    
2210
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
2211
                            if (gathering != null) {
2212
                                if (gathering.getLocality() != null) {
2213
                                    csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
2214
                                            .getText();
2215
                                }
2216
                                if (gathering.getCountry() != null) {
2217
                                    csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
2218
                                            .getLabel();
2219
                                }
2220
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2221
                                        state, gathering, fieldUnit);
2222

    
2223
                                if (gathering.getGatheringDate() != null) {
2224
                                    csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2225
                                            .getGatheringDate().toString();
2226
                                }
2227
                                if (!gathering.getCollectingAreas().isEmpty()) {
2228
                                    int index = 0;
2229
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2230
                                    for (NamedArea area : gathering.getCollectingAreas()) {
2231
                                        if (index == 0) {
2232
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2233
                                                    .getLevel().getLabel():"";
2234
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2235
                                        }
2236
                                        if (index == 1) {
2237
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2238
                                                    .getLevel().getLabel():"";
2239
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2240
                                        }
2241
                                        if (index == 2) {
2242
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2243
                                                    .getLevel().getLabel():"";
2244
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2245
                                        }
2246
                                        if (index == 3) {
2247
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2248
                                            break;
2249
                                        }
2250
                                        index++;
2251
                                    }
2252
                                }
2253
                            }
2254
                        }
2255
                    }
2256
                } else {
2257
                    state.getResult().addError("The specimen with uuid " + specimen.getUuid()
2258
                            + " is not an DerivedUnit. Could not be exported.");
2259
                }
2260
            }
2261

    
2262
            state.getProcessor().put(table, specimen, csvLine);
2263
        } catch (Exception e) {
2264
            state.getResult().addException(e, "An unexpected error occurred when handling specimen "
2265
                    + cdmBaseStr(specimen) + ": " + e.getMessage());
2266
        }
2267
    }
2268

    
2269
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
2270

    
2271
        String mediaUriString = "";
2272
        boolean first = true;
2273
        while (it.hasNext()) {
2274
            MediaRepresentation rep = it.next();
2275
            List<MediaRepresentationPart> parts = rep.getParts();
2276
            for (MediaRepresentationPart part : parts) {
2277
                if (first) {
2278
                    if (part.getUri() != null) {
2279
                        mediaUriString += part.getUri().toString();
2280
                        first = false;
2281
                    }
2282
                } else {
2283
                    if (part.getUri() != null) {
2284
                        mediaUriString += ", " + part.getUri().toString();
2285
                    }
2286
                }
2287
            }
2288
        }
2289

    
2290
        return mediaUriString;
2291
    }
2292

    
2293
    private String extractLinkUris(Iterator<ExternalLink> it) {
2294

    
2295
        String linkUriString = "";
2296
        boolean first = true;
2297
        while (it.hasNext()) {
2298
            ExternalLink link = it.next();
2299
            if (first) {
2300
                if (link.getUri() != null) {
2301
                    linkUriString += link.getUri().toString();
2302
                    first = false;
2303
                }
2304
            } else {
2305
                if (link.getUri() != null) {
2306
                    linkUriString += ", " + link.getUri().toString();
2307
                }
2308
            }
2309
        }
2310
        return linkUriString;
2311
    }
2312

    
2313
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2314
        try {
2315
            String collectorString = "";
2316
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2317
            if (gathering.getCollector() != null) {
2318
                if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2319

    
2320
                    Person primaryCollector = fieldUnit.getPrimaryCollector();
2321
                    if (collectorA instanceof Team) {
2322
                        Team collectorTeam = (Team) collectorA;
2323
                        boolean isFirst = true;
2324
                        for (Person member : collectorTeam.getTeamMembers()) {
2325
                            if (!isFirst) {
2326
                                collectorString += "; ";
2327
                            }
2328
                            if (member.equals(primaryCollector)) {
2329
                                // highlight
2330
                                collectorString += "<b>" + member.getTitleCache() + "</b>";
2331
                            } else {
2332
                                collectorString += member.getTitleCache();
2333
                            }
2334
                        }
2335
                    }
2336
                } else {
2337
                    collectorString = collectorA.getTitleCache();
2338
                }
2339
            }
2340
            return collectorString;
2341
        } catch (Exception e) {
2342
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2343
                    + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2344
            return "";
2345
        }
2346
    }
2347

    
2348
    /**
2349
     * Returns a string representation of the {@link CdmBase cdmBase} object for
2350
     * result messages.
2351
     */
2352
    private String cdmBaseStr(CdmBase cdmBase) {
2353
        if (cdmBase == null) {
2354
            return "-no object available-";
2355
        } else {
2356
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2357
        }
2358
    }
2359

    
2360
    @Override
2361
    protected boolean doCheck(CdmLightExportState state) {
2362
        return false;
2363
    }
2364

    
2365
    @Override
2366
    protected boolean isIgnore(CdmLightExportState state) {
2367
        return false;
2368
    }
2369

    
2370
}
(1-1/6)