Project

General

Profile

Download (75.3 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.Collections;
14
import java.util.HashSet;
15
import java.util.Iterator;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19
import java.util.UUID;
20

    
21
import org.apache.commons.lang3.StringUtils;
22
import org.springframework.stereotype.Component;
23

    
24
import eu.etaxonomy.cdm.common.CdmUtils;
25
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
26
import eu.etaxonomy.cdm.io.common.CdmExportBase;
27
import eu.etaxonomy.cdm.io.common.ExportResult.ExportResultState;
28
import eu.etaxonomy.cdm.io.common.ICdmExport;
29
import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
30
import eu.etaxonomy.cdm.model.agent.AgentBase;
31
import eu.etaxonomy.cdm.model.agent.Person;
32
import eu.etaxonomy.cdm.model.agent.Team;
33
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
34
import eu.etaxonomy.cdm.model.common.Annotation;
35
import eu.etaxonomy.cdm.model.common.AnnotationType;
36
import eu.etaxonomy.cdm.model.common.CdmBase;
37
import eu.etaxonomy.cdm.model.common.DefinedTerm;
38
import eu.etaxonomy.cdm.model.common.ICdmBase;
39
import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
40
import eu.etaxonomy.cdm.model.common.Language;
41
import eu.etaxonomy.cdm.model.common.LanguageString;
42
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
43
import eu.etaxonomy.cdm.model.description.DescriptionBase;
44
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
45
import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
46
import eu.etaxonomy.cdm.model.description.Distribution;
47
import eu.etaxonomy.cdm.model.description.Feature;
48
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
49
import eu.etaxonomy.cdm.model.description.SpecimenDescription;
50
import eu.etaxonomy.cdm.model.description.TaxonDescription;
51
import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
52
import eu.etaxonomy.cdm.model.description.TextData;
53
import eu.etaxonomy.cdm.model.location.NamedArea;
54
import eu.etaxonomy.cdm.model.media.Media;
55
import eu.etaxonomy.cdm.model.media.MediaRepresentation;
56
import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
57
import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
58
import eu.etaxonomy.cdm.model.name.HomotypicalGroupNameComparator;
59
import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
60
import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
61
import eu.etaxonomy.cdm.model.name.Rank;
62
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
63
import eu.etaxonomy.cdm.model.name.TaxonName;
64
import eu.etaxonomy.cdm.model.name.TypeComparator;
65
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
66
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
67
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
68
import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
69
import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
70
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
71
import eu.etaxonomy.cdm.model.reference.Reference;
72
import eu.etaxonomy.cdm.model.reference.ReferenceType;
73
import eu.etaxonomy.cdm.model.taxon.Classification;
74
import eu.etaxonomy.cdm.model.taxon.Synonym;
75
import eu.etaxonomy.cdm.model.taxon.Taxon;
76
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
77
import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
78

    
79
/**
80
 * @author k.luther
81
 * @date 15.03.2017
82
 */
83
@Component
84
public class CdmLightClassificationExport
85
            extends CdmExportBase<CdmLightExportConfigurator, CdmLightExportState, IExportTransformer, File>
86
            implements ICdmExport<CdmLightExportConfigurator, CdmLightExportState>{
87

    
88

    
89
    private static final long serialVersionUID = 2518643632756927053L;
90
    private static final String STD_TEAM_CONCATINATION = ", ";
91
    private static final String FINAL_TEAM_CONCATINATION = " & ";
92

    
93
    private static final String IPNI_NAME_IDENTIFIER = "Ipni Name Identifier";
94
    private static final String TROPICOS_NAME_IDENTIFIER = "Tropicos Name Identifier";
95
    private static final String WFO_NAME_IDENTIFIER = "WFO Name Identifier";
96

    
97
    public CdmLightClassificationExport() {
98
        super();
99
        this.ioName = this.getClass().getSimpleName();
100

    
101
    }
102

    
103
    /**
104
     * {@inheritDoc}
105
     */
106
    @Override
107
    protected void doInvoke(CdmLightExportState state) {
108
        try {
109
            CdmLightExportConfigurator config = state.getConfig();
110
            config.setFieldsTerminatedBy(",");
111

    
112
            if (config.getClassificationUuids().isEmpty()){
113
                //TODO
114
                state.setEmptyData();
115
                return;
116
            }
117
            //TODO MetaData
118
            for (UUID classificationUuid : config.getClassificationUuids()){
119
                handleSingleClassification(state, classificationUuid);
120
            }
121
            state.getProcessor().createFinalResult(state);
122
        } catch (Exception e) {
123
            state.getResult().addException(e, "An unexpected error occurred in main method doInvoke() " +
124
                    e.getMessage());
125
        }
126
    }
127

    
128
    /**
129
     * @param state
130
     * @param classificationUuid
131
     */
132
    private void handleSingleClassification(CdmLightExportState state, UUID classificationUuid) {
133
        try {
134
            Classification classification = getClassificationService().find(classificationUuid);
135

    
136
            if (classification == null){
137
                String message = String.format("Classification for given classification UUID not found. No data imported for %s", classificationUuid.toString());
138
                //TODO
139
                state.getResult().addWarning(message);
140
            }else{
141
                TaxonNode root = classification.getRootNode();
142

    
143
                UUID uuid = root.getUuid();
144

    
145
                root = getTaxonNodeService().load(uuid);
146
                for (TaxonNode child : root.getChildNodes()){
147
                    handleTaxon(state, child);
148
                    //TODO progress monitor
149
                }
150
            }
151
        } catch (Exception e) {
152
            state.getResult().addException(e, "An unexpected error occurred when handling classification " +
153
                    classificationUuid + ": " + e.getMessage() + e.getStackTrace());
154
        }
155
    }
156

    
157
    /**
158
     * @param state
159
     * @param taxon
160
     */
161
    private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
162

    
163
      //  Taxon taxon = taxonNode.getTaxon();
164
        if (taxonNode == null){
165
            state.getResult().addError ("The taxonNode was null.", "handleTaxon");
166
            state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
167
            return;
168
        }
169
        if (taxonNode.getTaxon() == null){
170
            state.getResult().addError ("There was a taxon node without a taxon: " + taxonNode.getUuid(), "handleTaxon");
171
            state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
172
        }else{
173
            Taxon taxon = taxonNode.getTaxon();
174
             try{
175
                TaxonName name = taxon.getName();
176
                handleName(state, name);
177
                for (Synonym syn : taxon.getSynonyms()){
178
                    handleSynonym(state, syn);
179
                }
180

    
181

    
182
                CdmLightExportTable table = CdmLightExportTable.TAXON;
183
                String[] csvLine = new String[table.getSize()];
184

    
185
                csvLine[table.getIndex(CdmLightExportTable.TAXON_ID)] = getId(state, taxon);
186
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
187
                Taxon parent = (taxonNode.getParent()==null) ? null : taxonNode.getParent().getTaxon();
188
                csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
189
                csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
190
                csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(taxon.getSec());
191
                csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state, taxonNode.getClassification());
192
                csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification().getTitleCache();
193

    
194
                state.getProcessor().put(table, taxon, csvLine);
195
                handleDescriptions(state, taxon);
196
             }catch(Exception e){
197
                 state.getResult().addException (e, "An unexpected problem occurred when trying to export "
198
                         + "taxon with id " + taxon.getId());
199
                 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
200
             }
201
       }
202

    
203
       taxonNode.removeNullValueFromChildren();
204
       for (TaxonNode child: taxonNode.getChildNodes()){
205
           handleTaxon(state, child);
206
       }
207

    
208
    }
209

    
210
    /**
211
     * @param state
212
     * @param taxon
213
     */
214
    private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
215
        if (cdmBase instanceof Taxon){
216
            Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
217
            Set<TaxonDescription> descriptions = taxon.getDescriptions();
218
            List<DescriptionElementBase> simpleFacts = new ArrayList<>();
219
            List<DescriptionElementBase> specimenFacts = new ArrayList<>();
220
            List<DescriptionElementBase> distributionFacts = new ArrayList<>();
221
            List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
222
            List<DescriptionElementBase> usageFacts = new ArrayList<>();
223
            for (TaxonDescription description: descriptions){
224
                if (description.getElements() != null){
225
                    for (DescriptionElementBase element: description.getElements()){
226
                        element = CdmBase.deproxy(element);
227
                        if (element.getFeature().equals(Feature.COMMON_NAME())){
228
                            commonNameFacts.add(element);
229
                        }else if (element.getFeature().equals(Feature.DISTRIBUTION())){
230
                            distributionFacts.add(element);
231
                        }else if (element instanceof IndividualsAssociation || isSpecimenFeature(element.getFeature())){
232
                            specimenFacts.add(element);
233
                        }else{
234
                            simpleFacts.add(element);
235
                        }
236
                    }
237
                }
238
            }
239
            if (!commonNameFacts.isEmpty()){
240
                handleCommonNameFacts(state, taxon, commonNameFacts);
241
            }
242
            if (!distributionFacts.isEmpty()){
243
                handleDistributionFacts(state, taxon, distributionFacts);
244
            }
245
            if (!specimenFacts.isEmpty()){
246
                handleSpecimenFacts(state, taxon, specimenFacts);
247
            }
248
            if (!simpleFacts.isEmpty()){
249
                handleSimpleFacts(state, taxon, simpleFacts);
250
            }
251
        } else if (cdmBase instanceof TaxonName){
252
            TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
253
            Set<TaxonNameDescription> descriptions = name.getDescriptions();
254
            List<DescriptionElementBase> simpleFacts = new ArrayList<>();
255
            for (TaxonNameDescription description: descriptions){
256
                if (description.getElements() != null){
257
                    for (DescriptionElementBase element: description.getElements()){
258
                        if (!element.getFeature().equals(Feature.PROTOLOGUE())){
259
                            simpleFacts.add(element);
260
                        }
261
                    }
262
                }
263
             }
264
            if (!simpleFacts.isEmpty()){
265
                handleSimpleFacts(state, name, simpleFacts);
266
            }
267
        }
268
    }
269

    
270

    
271
    /**
272
     * @param feature
273
     * @return
274
     */
275
    private boolean isSpecimenFeature(Feature feature) {
276
        //TODO allow user defined specimen features
277
        if (feature == null){
278
            return false;
279
        }else if (feature.isSupportsIndividualAssociation()){
280
            return true;
281
        }else{
282
            return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
283
                    || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
284
                    || feature.equals(Feature.OCCURRENCE())
285
                     ;
286
        }
287
    }
288

    
289
    /**
290
     * @param state
291
     * @param taxon
292
     * @param simpleFacts
293
     */
294
    private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
295
            List<DescriptionElementBase> simpleFacts) {
296
        try {
297
            CdmLightExportTable table = CdmLightExportTable.SIMPLE_FACT;
298

    
299
            for (DescriptionElementBase element: simpleFacts){
300
                handleSingleSimpleFact(state, cdmBase, table, element);
301
            }
302
        } catch (Exception e) {
303
            state.getResult().addException(e, "An unexpected error occurred when handling simple facts for " +
304
                    cdmBaseStr(cdmBase) + ": " + e.getMessage());
305
        }
306
    }
307

    
308
    /**
309
     * @param state
310
     * @param cdmBase
311
     * @param table
312
     * @param element
313
     */
314
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
315
            DescriptionElementBase element) {
316
        try {
317
            String[] csvLine;
318
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
319

    
320
            if (element instanceof TextData){
321
               TextData textData = (TextData)element;
322
               csvLine = new String[table.getSize()];
323
               csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
324
               if (cdmBase instanceof Taxon){
325
                   csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
326
                   csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
327
               }else if (cdmBase instanceof TaxonName){
328
                   csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
329
                   csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
330
               }
331
               csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
332

    
333
               String mediaUris = "";
334
               for (Media media: textData.getMedia()){
335
                   String mediaString = extractMediaUris(media.getRepresentations().iterator());
336
                   if (!StringUtils.isBlank(mediaString)){
337
                       mediaUris +=  mediaString + ";";
338
                   }
339
                   else{
340
                       state.getResult().addWarning("Empty Media object for uuid: " +
341
                               cdmBase.getUuid() + " uuid of media: " + media.getUuid());
342
                   }
343
               }
344
               csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
345
               if (textData.getFeature().equals(Feature.CITATION())){
346
                  // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
347
                   state.getProcessor().put(table, textData, csvLine);
348
               }else if (!textData.getMultilanguageText().isEmpty()){
349
                   for (Language language: textData.getMultilanguageText().keySet()){
350
                       String[] csvLineLanguage = csvLine.clone();
351
                       LanguageString langString = textData.getLanguageText(language);
352

    
353
                       csvLineLanguage[table.getIndex(CdmLightExportTable.FACT_TEXT)] = langString.getText();
354
                       csvLineLanguage[table.getIndex(CdmLightExportTable.LANGUAGE)] = language.getLabel();
355
                       state.getProcessor().put(table, textData, csvLineLanguage);
356
                   }
357
               } else{
358
                   state.getProcessor().put(table, textData, csvLine);
359
               }
360
            }
361
        } catch (Exception e) {
362
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact " +
363
                    cdmBaseStr(element) + ": " + e.getMessage());
364
        }
365
    }
366

    
367

    
368
    /**
369
     * @param state
370
     * @param specimenFacts
371
     */
372
    private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> specimenFacts) {
373
        CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
374

    
375
        for (DescriptionElementBase element: specimenFacts){
376
            try {
377
                String[] csvLine = new String[table.getSize()];
378
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
379
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
380
                handleSource(state, element, table);
381
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(element.getAnnotations());
382

    
383
                if (element instanceof IndividualsAssociation){
384

    
385
                    IndividualsAssociation indAssociation = (IndividualsAssociation)element;
386
                    if (state.getSpecimenFromStore(indAssociation.getAssociatedSpecimenOrObservation().getId()) == null){
387
                        SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(indAssociation.getAssociatedSpecimenOrObservation());
388

    
389
                        if (specimenBase instanceof SpecimenOrObservationBase){
390
                            SpecimenOrObservationBase derivedUnit = specimenBase;
391
                            handleSpecimen(state, derivedUnit);
392
                            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, indAssociation.getAssociatedSpecimenOrObservation());
393
                        }else{
394
                            //field units are not supported
395
                            state.getResult().addError("The associated Specimen of taxon " + taxon.getUuid() + " is not an DerivedUnit. Could not be exported.");
396
                        }
397
                    }
398
                } else if (element instanceof TextData){
399
                    TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
400
                    csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(textData.getMultilanguageText());
401
                }
402
                state.getProcessor().put(table, element, csvLine);
403
            } catch (Exception e) {
404
                state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact " +
405
                        cdmBaseStr(element) + ": " + e.getMessage());
406
            }
407
        }
408
    }
409

    
410
    /**
411
     * @param multilanguageText
412
     * @return
413
     */
414
    private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
415
       String text = "";
416
       int index = multilanguageText.size();
417
       for(LanguageString langString: multilanguageText.values()){
418
           text += langString.getText();
419
           if (index > 1){
420
               text += "; ";
421
           }
422
           index --;
423
       }
424

    
425
        return text;
426
    }
427

    
428
    /**
429
     * @param annotations
430
     * @return
431
     */
432
    private String createAnnotationsString(Set<Annotation> annotations) {
433
        StringBuffer strBuff = new StringBuffer();
434

    
435
        for (Annotation ann:annotations){
436
            if (ann.getAnnotationType() == null ||!ann.getAnnotationType().equals(AnnotationType.TECHNICAL())){
437
                strBuff.append(ann.getText());
438
                strBuff.append("; ");
439
            }
440
        }
441

    
442
        if (strBuff.length() > 2){
443
            return strBuff.substring(0, strBuff.length()-2);
444
        }else{
445
            return null;
446
        }
447
    }
448

    
449
    /**
450
     * @param state
451
     * @param taxon
452
     * @param element
453
     */
454
    private void handleSource(CdmLightExportState state, DescriptionElementBase element, CdmLightExportTable factsTable) {
455
        CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
456
        Set<DescriptionElementSource> sources = element.getSources();
457
        for (DescriptionElementSource source: sources){
458
            try {
459
                String[] csvLine = new  String[table.getSize()];
460
                Reference ref = source.getCitation();
461
                if ((ref == null) && (source.getNameUsedInSource() == null)){
462
                    continue;
463
                }
464
                if (ref != null){
465
                    if (state.getReferenceFromStore(ref.getId()) == null){
466
                        handleReference(state, ref);
467
                        csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
468
                    }
469
                }
470
                csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
471

    
472
                csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state, source.getNameUsedInSource());
473
                csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
474
                if ( StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])  && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])){
475
                    continue;
476
                }
477
                state.getProcessor().put(table, source, csvLine);
478
            } catch (Exception e) {
479
                state.getResult().addException(e, "An unexpected error occurred when handling single source " +
480
                        cdmBaseStr(element) + ": " + e.getMessage());
481
            }
482
        }
483

    
484
    }
485

    
486
    /**
487
     * @param state
488
     * @param distributionFacts
489
     */
490
    private void handleDistributionFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> distributionFacts) {
491
        CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
492

    
493
        for (DescriptionElementBase element: distributionFacts){
494
            try {
495
                if (element instanceof Distribution){
496
                    String[] csvLine = new  String[table.getSize()];
497
                    Distribution distribution = (Distribution)element;
498
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
499
                    handleSource(state, element, table);
500
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
501
                    if (distribution.getArea() != null){
502
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = distribution.getArea().getLabel();
503
                    }
504
                    if (distribution.getStatus() != null){
505
                        csvLine[table.getIndex(CdmLightExportTable.STATUS_LABEL)] = distribution.getStatus().getLabel();
506
                    }
507
                    state.getProcessor().put(table, distribution, csvLine);
508
                } else{
509
                    state.getResult().addError("The distribution description for the taxon " + taxon.getUuid() + " is not of type distribution. Could not be exported. UUID of the description element: " + element.getUuid());
510
                }
511
            } catch (Exception e) {
512
                state.getResult().addException(e, "An unexpected error occurred when handling single distribution " +
513
                        cdmBaseStr(element) + ": " + e.getMessage());
514
            }
515
        }
516
    }
517

    
518
    /**
519
     * @param state
520
     * @param commonNameFacts
521
     */
522
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> commonNameFacts) {
523
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
524

    
525
        for (DescriptionElementBase element: commonNameFacts){
526
            try {
527
                if (element instanceof CommonTaxonName){
528
                    String[] csvLine = new  String[table.getSize()];
529
                    CommonTaxonName commonName = (CommonTaxonName)element;
530
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
531
                    handleSource(state, element, table);
532
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
533
                    if (commonName.getName() != null){csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();}
534
                    if (commonName.getLanguage() != null){csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();}
535
                    if (commonName.getArea() != null){ csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();}
536
                    state.getProcessor().put(table, commonName, csvLine);
537
                } else{
538
                    state.getResult().addError("The distribution description for the taxon " + taxon.getUuid() + " is not of type distribution. Could not be exported. UUID of the description element: " + element.getUuid());
539
                }
540
            } catch (Exception e) {
541
                state.getResult().addException(e, "An unexpected error occurred when handling single common name " +
542
                        cdmBaseStr(element) + ": " + e.getMessage());
543
            }
544
        }
545
    }
546

    
547
    /**
548
     * @param sec
549
     * @return
550
     */
551
    private String getTitleCache(IIdentifiableEntity identEntity) {
552
        if (identEntity == null){
553
            return "";
554
        }
555
        //TODO refresh?
556
        return identEntity.getTitleCache();
557
    }
558

    
559
    /**
560
     * @param state
561
     * @param taxon
562
     * @return
563
     */
564
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
565
        if (cdmBase == null){
566
            return "";
567
        }
568
        //TODO make configurable
569
        return cdmBase.getUuid().toString();
570
    }
571

    
572
    /**
573
     * @param state
574
     * @param syn
575
     */
576
    private void handleSynonym(CdmLightExportState state, Synonym syn) {
577
       try {
578
           TaxonName name = syn.getName();
579
           handleName(state, name);
580

    
581
           CdmLightExportTable table = CdmLightExportTable.SYNONYM;
582
           String[] csvLine = new String[table.getSize()];
583

    
584
           csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, syn);
585
           csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, syn.getAcceptedTaxon());
586
           csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
587
           csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, syn.getSec());
588
           csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(syn.getSec());
589

    
590
           state.getProcessor().put(table, syn, csvLine);
591
        } catch (Exception e) {
592
            state.getResult().addException(e, "An unexpected error occurred when handling synonym " +
593
                    cdmBaseStr(syn) + ": " + e.getMessage());
594
        }
595
    }
596

    
597
    /**
598
     * @param state
599
     * @param name
600
     */
601
    private void handleName(CdmLightExportState state, TaxonName name) {
602
        if (name == null){
603
            return;
604
        }
605
        try {
606
            Rank rank = name.getRank();
607
            CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
608
            name = HibernateProxyHelper.deproxy(name);
609
            String[] csvLine = new String[table.getSize()];
610

    
611
            csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
612
            if (name.getLsid() != null){
613
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
614
            }else{
615
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
616
            }
617

    
618
            handleIdentifier(state, name);
619
            handleDescriptions(state, name);
620

    
621
            csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
622
            if (rank != null){
623
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
624
                if (rank.isInfraGeneric()){
625
                    try {
626
                        csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank().getInfraGenericMarker();
627
                    } catch (UnknownCdmTypeException e) {
628
                        state.getResult().addError("Infrageneric marker expected but not available for rank " + name.getRank().getTitleCache());
629
                    }
630
                }
631
                if (rank.isInfraSpecific()){
632
                    csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
633
                }
634
            }else{
635
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
636
            }
637
            if (name.isProtectedTitleCache()){
638
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] =name.getTitleCache();
639
            }else{
640
                //TODO: adapt the tropicos titlecache creation
641
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
642
            }
643
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
644
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
645

    
646
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
647
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
648

    
649
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
650
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state,name.getBasionymAuthorship());
651
            if (name.getBasionymAuthorship() != null){
652
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
653
                    handleAuthor(state, name.getBasionymAuthorship());
654
                }
655
            }
656
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state, name.getExBasionymAuthorship());
657
            if (name.getExBasionymAuthorship() != null){
658
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
659
                    handleAuthor(state, name.getExBasionymAuthorship());
660
                }
661

    
662
            }
663
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,name.getCombinationAuthorship());
664
            if (name.getCombinationAuthorship() != null){
665
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
666
                    handleAuthor(state, name.getCombinationAuthorship());
667
                }
668
            }
669
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state, name.getExCombinationAuthorship());
670
            if (name.getExCombinationAuthorship() != null){
671
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
672
                    handleAuthor(state, name.getExCombinationAuthorship());
673
                }
674

    
675
            }
676

    
677
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
678

    
679
            Reference nomRef = (Reference)name.getNomenclaturalReference();
680

    
681
            if (nomRef != null){
682
                if (state.getReferenceFromStore(nomRef.getId()) == null){
683
                    handleReference(state, nomRef);
684
                }
685
                csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
686
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
687
                if (nomRef.getVolume() != null){
688
                    csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
689
                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
690
                }
691
                if (nomRef.getDatePublished() != null){
692
                    csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
693
                    csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
694
                    csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = null;
695
                }
696
                if (name.getNomenclaturalMicroReference() != null){
697
                    csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
698
                }
699
                nomRef = HibernateProxyHelper.deproxy(nomRef);
700
                if (nomRef.getInReference() != null){
701
                    Reference inReference = nomRef.getInReference();
702
                    if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null){
703
                        csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference.getDatePublishedString();
704
                        csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished().getYear();
705
                    }
706
                    if (nomRef.getVolume() == null && inReference.getVolume() != null){
707
                        csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
708
                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
709
                    }
710
                    if (inReference.getInReference() != null){
711
                        inReference = inReference.getInReference();
712
                    }
713
                    if (inReference.getAbbrevTitle() == null){
714
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(inReference.getAbbrevTitleCache());
715
                    }else{
716
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(inReference.getAbbrevTitle());
717
                    }
718
                    if (inReference.getTitle() == null){
719
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitleCache());
720
                    }else{
721
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
722
                    }
723

    
724

    
725
                    TeamOrPersonBase<?> author = inReference.getAuthorship();
726
                    if (author != null && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))){
727
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = CdmUtils.Nz(author.getNomenclaturalTitle());
728
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils.Nz(author.getTitleCache());
729
                    }else{
730
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
731
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
732
                    }
733
                }else{
734
                    if (nomRef.getAbbrevTitle() == null){
735
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(nomRef.getAbbrevTitleCache());
736
                    }else{
737
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(nomRef.getAbbrevTitle());
738
                    }
739
                    if (nomRef.getTitle() == null){
740
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitleCache());
741
                    }else{
742
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
743
                    }
744
                    TeamOrPersonBase<?> author = nomRef.getAuthorship();
745
                    if (author != null ){
746
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = CdmUtils.Nz(author.getNomenclaturalTitle());
747
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils.Nz(author.getTitleCache());
748
                    }else{
749
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
750
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
751
                    }
752

    
753
                }
754
            }else{
755
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
756
            }
757

    
758

    
759

    
760
            /*
761
            * Collation
762

    
763
            Detail
764

    
765

    
766
            TitlePageYear
767
            */
768
            Set<TaxonNameDescription> descriptions = name.getDescriptions();
769
            String protologueUriString = extractURIs(state, descriptions, Feature.PROTOLOGUE());
770

    
771
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
772

    
773
            if (name.getStatus() == null || name.getStatus().isEmpty()){
774
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
775
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
776
            }else{
777

    
778
                String statusStringAbbrev = extractStatusString(state, name, true);
779
                String statusString = extractStatusString(state, name, false);
780

    
781
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
782
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
783
            }
784

    
785
            HomotypicalGroup group =name.getHomotypicalGroup();
786

    
787
            if (state.getHomotypicalGroupFromStore(group.getId()) == null){
788
                handleHomotypicalGroup(state, group);
789
            }
790
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
791
            List<TaxonName> typifiedNames = new ArrayList<>();
792
            typifiedNames.addAll(group.getTypifiedNames());
793
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
794
            Integer  seqNumber= typifiedNames.indexOf(name);
795
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
796
            state.getProcessor().put(table, name, csvLine);
797

    
798
            /*
799
             *
800
            Tropicos_ID
801
            IPNI_ID
802

    
803

    
804
            InfragenericRank
805

    
806

    
807
            InfraspecificRank
808
            Collation
809
            Volume (Issue)
810
            Detail
811
            DatePublished
812
            YearPublished
813
            TitlePageYear
814

    
815

    
816

    
817
            HomotypicGroupSequenceNumber
818

    
819

    
820
             *
821
             */
822
        } catch (Exception e) {
823
            state.getResult().addException(e, "An unexpected error occurred when handling synonym " +
824
                    cdmBaseStr(name) + ": " + e.getMessage());
825
        }
826
    }
827

    
828
    /**
829
     * @return
830
     */
831
    private String createCollatation(TaxonName name) {
832
        String collation = "";
833
        if (name.getNomenclaturalReference() != null){
834
            Reference ref = (Reference) name.getNomenclaturalReference();
835
            collation = getVolume(ref);
836
        }
837
        if (name.getNomenclaturalMicroReference() != null){
838
            if (!StringUtils.isBlank(collation)){
839
                collation += ":";
840
            }
841
            collation +=name.getNomenclaturalMicroReference();
842
        }
843

    
844
        return collation;
845
    }
846

    
847
    /**
848
     * @param nomenclaturalReference
849
     * @return
850
     */
851
    private String getVolume(Reference reference) {
852
        if (reference.getVolume() != null){
853
            return reference.getVolume();
854
        }else if (reference.getInReference() != null){
855
            if (reference.getInReference().getVolume() != null){
856
                return reference.getInReference().getVolume();
857
            }
858
        }
859
        return null;
860
    }
861

    
862
    /**
863
     * @param state
864
     * @param name
865
     */
866
    private void handleIdentifier(CdmLightExportState state, TaxonName name) {
867
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
868
        String[] csvLine;
869
        try {
870
            Set<String>  IPNIidentifiers = name.getIdentifiers(DefinedTerm.IPNI_NAME_IDENTIFIER());
871
            Set<String>  tropicosIdentifiers = name.getIdentifiers(DefinedTerm.TROPICOS_NAME_IDENTIFIER());
872
            Set<String>  WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
873
            if (!IPNIidentifiers.isEmpty()){
874
                csvLine = new String[table.getSize()];
875
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
876
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
877
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(IPNIidentifiers);
878
                state.getProcessor().put(table, name, csvLine);
879
            }
880
            if (!tropicosIdentifiers.isEmpty()){
881
                csvLine = new String[table.getSize()];
882
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
883
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
884
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(tropicosIdentifiers);
885
                state.getProcessor().put(table, name, csvLine);
886
            }
887
            if (!WFOIdentifiers.isEmpty()){
888
                csvLine = new String[table.getSize()];
889
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
890
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
891
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(WFOIdentifiers);
892
                state.getProcessor().put(table, name, csvLine);
893
            }
894
        } catch (Exception e) {
895
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for " +
896
                    cdmBaseStr(name) + ": " + e.getMessage());
897

    
898
        }
899
    }
900

    
901
    /**
902
     * @param tropicosIdentifiers
903
     */
904
    private String extractIdentifier(Set<String> identifierSet) {
905

    
906
        String identifierString = "";
907
        for (String identifier: identifierSet){
908
            if (!StringUtils.isBlank(identifierString)){
909
                identifierString += ", ";
910
            }
911
            identifierString += identifier;
912
        }
913

    
914
        return identifierString;
915
    }
916

    
917
    /**
918
     * @param state
919
     * @param descriptions
920
     * @return
921
     */
922
    private String extractURIs(CdmLightExportState state,
923
            Set<? extends DescriptionBase<?>> descriptionsSet, Feature feature) {
924
        String mediaUriString = "";
925
        SpecimenDescription specimenDescription;
926
        TaxonDescription taxonDescription;
927
        TaxonNameDescription nameDescription;
928
        Set<DescriptionElementBase> elements = new HashSet<>();
929
        for (DescriptionBase<?> description : descriptionsSet){
930
            try {
931
                if (!description.getElements().isEmpty()){
932
                    if (description instanceof SpecimenDescription){
933
                        specimenDescription = (SpecimenDescription)description;
934
                        elements = specimenDescription.getElements();
935
                    }else if (description instanceof TaxonDescription){
936
                        taxonDescription = (TaxonDescription) description;
937
                        elements = taxonDescription.getElements();
938
                    } else if (description instanceof TaxonNameDescription){
939
                        nameDescription = (TaxonNameDescription) description;
940
                        elements = nameDescription.getElements();
941
                    }
942

    
943
                    for (DescriptionElementBase element : elements){
944
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
945
                        if (entityFeature.equals(feature)){
946
                            if (!element.getMedia().isEmpty()){
947
                                List<Media> media = element.getMedia();
948
                                for (Media mediaElement: media){
949
                                    Iterator<MediaRepresentation> it =  mediaElement.getRepresentations().iterator();
950
                                    mediaUriString = extractMediaUris(it);
951
                                }
952
                            }
953
                        }
954
                    }
955
                }
956
            } catch (Exception e) {
957
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for " +
958
                        cdmBaseStr(description) + ": " + e.getMessage());
959
            }
960
        }
961
        return mediaUriString;
962
    }
963

    
964
    /**
965
     * @param state
966
     * @param basionymAuthorship
967
     */
968
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
969
        try {
970
            if (state.getAuthorFromStore(author.getId()) != null){
971
                return;
972
            }
973
            state.addAuthorToStore(author);
974
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
975
            String[] csvLine = new String[table.getSize()];
976
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
977
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
978
            String[] csvLineMember = new String[table.getSize()];
979
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
980
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.getNomenclaturalTitle();
981
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
982
            author = HibernateProxyHelper.deproxy(author);
983
            if (author instanceof Person){
984
                Person authorPerson = (Person)author;
985
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FIRST_NAME)] = authorPerson.getFirstname();
986
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_LASTNAME)] = authorPerson.getLastname();
987
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
988
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
989
            } else{
990
                // create an entry in rel table and all members in author table, check whether the team members already in author table
991

    
992
                Team authorTeam = (Team)author;
993
                int index = 0;
994
                for (Person member: authorTeam.getTeamMembers()){
995
                    csvLineRel = new String[tableAuthorRel.getSize()];
996
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
997
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
998
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String.valueOf(index);
999
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() +":" +member.getId(), csvLineRel);
1000

    
1001
                    if (state.getAuthorFromStore(member.getId()) == null){
1002
                        state.addAuthorToStore(member);
1003
                        csvLineMember = new String[table.getSize()];
1004
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1005
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member.getNomenclaturalTitle();
1006
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1007
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FIRST_NAME)] = member.getFirstname();
1008
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_LASTNAME)] = member.getLastname();
1009
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1010
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1011
                        state.getProcessor().put(table, member, csvLineMember);
1012
                    }
1013
                    index++;
1014

    
1015
                }
1016
            }
1017
            state.getProcessor().put(table, author, csvLine);
1018
        } catch (Exception e) {
1019
            state.getResult().addException(e, "An unexpected error occurred when handling author " +
1020
                    cdmBaseStr(author) + ": " + e.getMessage());
1021
        }
1022
    }
1023

    
1024
    /**
1025
     * @param state
1026
     * @param name
1027
     * @param statusString
1028
     * @return
1029
     */
1030
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1031
        try {
1032
            Set<NomenclaturalStatus> status = name.getStatus();
1033
            if (status.isEmpty()){
1034
                return "";
1035
            }
1036
            String statusString = "";
1037
            for (NomenclaturalStatus nameStatus: status){
1038
                if (nameStatus != null){
1039
                    if (abbrev){
1040
                        if (nameStatus.getType() != null){
1041
                            statusString += nameStatus.getType().getIdInVocabulary();
1042
                        }
1043
                    }else{
1044
                        if (nameStatus.getType() != null){
1045
                            statusString += nameStatus.getType().getTitleCache();
1046
                        }
1047
                    }
1048
                    if (!abbrev){
1049

    
1050
                        if (nameStatus.getRuleConsidered() != null && !StringUtils.isBlank(nameStatus.getRuleConsidered())){
1051
                            statusString += " " + nameStatus.getRuleConsidered();
1052
                        }
1053
                        if (nameStatus.getCitation() != null){
1054
                            statusString += " " + nameStatus.getCitation().getTitleCache();
1055
                        }
1056
                        if (nameStatus.getCitationMicroReference() != null && !StringUtils.isBlank(nameStatus.getCitationMicroReference())){
1057
                            statusString += " " + nameStatus.getCitationMicroReference();
1058
                        }
1059
                    }
1060
                    statusString += " ";
1061
                }
1062
            }
1063
            return statusString;
1064
        } catch (Exception e) {
1065
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for " +
1066
                    cdmBaseStr(name) + ": " + e.getMessage());
1067
            return "";
1068
        }
1069
    }
1070

    
1071
    /**
1072
     * @param group
1073
     */
1074
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group) {
1075
        try {
1076
            state.addHomotypicalGroupToStore(group);
1077
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1078
            String[] csvLine = new String[table.getSize()];
1079

    
1080
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1081
            List<TaxonName> typifiedNames = new ArrayList<>();
1082
            typifiedNames.addAll(group.getTypifiedNames());
1083
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1084
            String typifiedNamesString = "";
1085
            for (TaxonName name: typifiedNames){
1086
                //Concatenated output string for homotypic group (names and citations) + status + some name relations (e.g. “non”)
1087
                //TODO: nameRelations, which and how to display
1088

    
1089

    
1090
                typifiedNamesString += name.getTitleCache()+ extractStatusString(state, name, true) + "; ";
1091
            }
1092
            typifiedNamesString = typifiedNamesString.substring(0, typifiedNamesString.length()-2);
1093
            if (typifiedNamesString != null){
1094
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
1095
            }else{
1096
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
1097
            }
1098
            Set<TypeDesignationBase> typeDesigantions = group.getTypeDesignations();
1099
            List<TypeDesignationBase> designationList = new ArrayList<>();
1100
            designationList.addAll(typeDesigantions);
1101
            Collections.sort(designationList, new TypeComparator());
1102
            StringBuffer typeDesignationString = new StringBuffer();
1103
            for (TypeDesignationBase typeDesignation: typeDesigantions){
1104
                if (typeDesignation != null && typeDesignation.getTypeStatus() != null){
1105
                    typeDesignationString.append(typeDesignation.getTypeStatus().getTitleCache() + ": ");
1106
                }
1107
                if (typeDesignation instanceof SpecimenTypeDesignation){
1108
                    if (((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen() != null){
1109
                        typeDesignationString.append(((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen().getTitleCache());
1110
                        handleSpecimen(state, ((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen());
1111
                    }
1112
                }else{
1113
                    if (((NameTypeDesignation)typeDesignation).getTypeName() != null){
1114
                        typeDesignationString.append(((NameTypeDesignation)typeDesignation).getTypeName().getTitleCache());
1115
                    }
1116
                }
1117
                if(typeDesignation.getCitation() != null ){
1118
                    typeDesignationString.append(", "+typeDesignation.getCitation().getTitleCache());
1119
                }
1120
                //TODO...
1121
                /*
1122
                 * Sortierung:
1123
                1.  Status der Typen: a) holo, lecto, neo, syn, b) epi, paralecto, c) para (wenn überhaupt) – die jeweiligen iso immer direct mit dazu
1124
                2.  Land
1125
                3.  Sammler
1126
                4.  Nummer
1127

    
1128
                Aufbau der Typusinformationen:
1129
                Land: Lokalität mit Höhe und Koordinaten; Datum; Sammler Nummer (Herbar/Barcode, Typusart; Herbar/Barcode, Typusart …)
1130

    
1131
                 */
1132
            }
1133
            String typeDesignations = typeDesignationString.toString();
1134
            if (typeDesignations != null){
1135
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = typeDesignations;
1136
            }else{
1137
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
1138
            }
1139
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
1140
        } catch (Exception e) {
1141
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group " +
1142
                    cdmBaseStr(group) + ": " + e.getMessage());
1143
        }
1144
    }
1145

    
1146
    /**
1147
     * @param name
1148
     * @return
1149
     */
1150
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
1151
        try {
1152
            String basionymStart = "(";
1153
            String basionymEnd = ") ";
1154
            String exAuthorSeperator = " ex ";
1155
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
1156
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
1157
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
1158
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
1159

    
1160
            String combinationAuthorString = "";
1161
            if (combinationAuthor != null){
1162
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
1163
                if (combinationAuthor instanceof Team){
1164
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
1165
                }else{
1166
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
1167
                    combinationAuthorString = createTropicosAuthorString(person);
1168
                }
1169
            }
1170
            String exCombinationAuthorString = "";
1171
            if (exCombinationAuthor != null){
1172
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
1173
                if (exCombinationAuthor instanceof Team){
1174
                   exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
1175
                }else{
1176
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
1177
                    exCombinationAuthorString = createTropicosAuthorString(person);
1178
                }
1179
            }
1180

    
1181
            String basionymAuthorString = "";
1182
            if (basionymAuthor != null){
1183
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
1184
                if (basionymAuthor instanceof Team){
1185
                    basionymAuthorString =  createTropicosTeamTitle(basionymAuthor);
1186
                }else{
1187
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
1188
                    basionymAuthorString = createTropicosAuthorString(person);
1189
                }
1190
            }
1191

    
1192
            String exBasionymAuthorString = "";
1193

    
1194
            if (exBasionymAuthor != null){
1195
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
1196
                if (exBasionymAuthor instanceof Team){
1197
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
1198

    
1199
                }else{
1200
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
1201
                    exBasionymAuthorString = createTropicosAuthorString(person);
1202
                }
1203
            }
1204
            String completeAuthorString =  name.getNameCache() + " ";
1205

    
1206
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString) || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart: "";
1207
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)) ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator): "" ;
1208
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString))? CdmUtils.Nz(basionymAuthorString):"";
1209
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString) || !CdmUtils.isBlank(basionymAuthorString)) ?  basionymEnd:"";
1210
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString)) ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator): "" ;
1211
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString))? CdmUtils.Nz(combinationAuthorString):"";
1212

    
1213

    
1214
            return completeAuthorString;
1215
        } catch (Exception e) {
1216
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for " +
1217
                    cdmBaseStr(name) + ": " + e.getMessage());
1218
            return null;
1219
        }
1220
    }
1221

    
1222
    /**
1223
     * @param combinationAuthor
1224
     * @return
1225
     */
1226
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
1227
        String combinationAuthorString;
1228
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
1229
        Team tempTeam = Team.NewInstance();
1230
        for (Person teamMember:team.getTeamMembers()){
1231
            combinationAuthorString = createTropicosAuthorString(teamMember);
1232
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
1233
            tempTeam.addTeamMember(tempPerson);
1234
        }
1235
        combinationAuthorString = tempTeam.generateTitle();
1236
        return combinationAuthorString;
1237
    }
1238

    
1239
    /**
1240
     * @param teamMember
1241
     */
1242
    private String createTropicosAuthorString(Person teamMember) {
1243
        String nomAuthorString = "";
1244
        String[] splittedAuthorString = null;
1245
        if (teamMember == null){
1246
            return nomAuthorString;
1247
        }
1248

    
1249
        if (teamMember.getFirstname() != null){
1250
            String firstNameString = teamMember.getFirstname().replaceAll("\\.", "\\. ");
1251
            splittedAuthorString = firstNameString.split("\\s");
1252
            for (String split: splittedAuthorString){
1253
                if (!StringUtils.isBlank(split)){
1254
                    nomAuthorString += split.substring(0, 1);
1255
                    nomAuthorString += ".";
1256
                }
1257
            }
1258
        }
1259
        if (teamMember.getLastname() != null){
1260
            String lastNameString = teamMember.getLastname().replaceAll("\\.", "\\. ");
1261
            splittedAuthorString = lastNameString.split("\\s");
1262
            for (String split: splittedAuthorString){
1263
                nomAuthorString += " " +split;
1264
            }
1265
        }
1266
        if (StringUtils.isBlank(nomAuthorString.trim())){
1267
            if (teamMember.getTitleCache() != null) {
1268
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
1269
                splittedAuthorString = titleCacheString.split("\\s");
1270
            }
1271

    
1272

    
1273
            int index = 0;
1274
            for (String split: splittedAuthorString){
1275
                if ( index < splittedAuthorString.length-1 && (split.length()==1 || split.endsWith("."))){
1276
                    nomAuthorString += split;
1277
                }else{
1278
                    nomAuthorString = nomAuthorString +" "+ split;
1279
                }
1280
                index++;
1281
            }
1282
        }
1283
        return nomAuthorString.trim();
1284
    }
1285

    
1286
    /**
1287
     * @param state
1288
     * @param name
1289
     */
1290
    private void handleReference(CdmLightExportState state, Reference reference) {
1291
        try {
1292
            state.addReferenceToStore(reference);
1293
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
1294

    
1295
            String[] csvLine = new String[table.getSize()];
1296
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
1297
            //TODO short citations correctly
1298
            String shortCitation = createShortCitation(reference);  //Should be Author(year) like in Taxon.sec
1299
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
1300
            //TODO get preferred title
1301
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.getTitle();
1302
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.getAbbrevTitle();
1303
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
1304
            //TBC
1305
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
1306
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
1307
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
1308
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
1309
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
1310
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
1311
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
1312
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
1313
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
1314
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
1315
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
1316
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
1317
            if ( reference.getAuthorship() != null){
1318
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = reference.getAuthorship().getTitleCache();
1319
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state,reference.getAuthorship());
1320
            }
1321

    
1322
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
1323
            if (reference.getInReference() != null && state.getReferenceFromStore(reference.getInReference().getId()) == null){
1324
                handleReference(state, reference.getInReference());
1325
            }
1326
            if ( reference.getInstitution() != null){ csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();}
1327
            if ( reference.getLsid() != null){ csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();}
1328
            if ( reference.getSchool() != null){ csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();}
1329
            if ( reference.getUri() != null){ csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();}
1330
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
1331

    
1332
            state.getProcessor().put(table, reference, csvLine);
1333
        } catch (Exception e) {
1334
            state.getResult().addException(e, "An unexpected error occurred when handling reference " +
1335
                    cdmBaseStr(reference) + ": " + e.getMessage());
1336
        }
1337

    
1338
    }
1339

    
1340

    
1341
    /**
1342
     * @param reference
1343
     * @return
1344
     */
1345
    private String createShortCitation(Reference reference) {
1346
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
1347
        String shortCitation = "";
1348
        if (authorship == null) {
1349
            return null;
1350
        }
1351
        authorship = HibernateProxyHelper.deproxy(authorship);
1352
        if (authorship instanceof Person){ shortCitation = ((Person)authorship).getLastname();}
1353
        else if (authorship instanceof Team){
1354

    
1355
            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
1356
            int index = 0;
1357

    
1358
            for (Person teamMember : authorTeam.getTeamMembers()){
1359
                index++;
1360
                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
1361
                shortCitation += concat + teamMember.getLastname();
1362
            }
1363

    
1364
        }
1365
        if (reference.getYear() != null){
1366
            shortCitation = shortCitation + " (" + reference.getYear() + ")";
1367
        }
1368
        return shortCitation;
1369
    }
1370

    
1371
    private static String concatString(Team team, List<Person> teamMembers, int i) {
1372
        String concat;
1373
        if (i <= 1){
1374
            concat = "";
1375
        }else if (i < teamMembers.size() || ( team.isHasMoreMembers() && i == teamMembers.size())){
1376
            concat = STD_TEAM_CONCATINATION;
1377
        }else{
1378
            concat = FINAL_TEAM_CONCATINATION;
1379
        }
1380
        return concat;
1381
    }
1382

    
1383
    /*
1384
     * TypeDesignation table
1385
     * Specimen_Fk
1386
     *  EditName_Fk
1387
     *   TypeVerbatimCitation
1388
     *   TypeCategory
1389
     *   TypeDesignatedByString
1390
     *   TypeDesignatedByRef_Fk
1391
     */
1392

    
1393
    private void handleSpecimenTypeDesignations(CdmLightExportState state, TaxonName name){
1394
       try {
1395
           Set<SpecimenTypeDesignation> typeDesignations = name.getSpecimenTypeDesignations();
1396
           CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1397
           String nameId = getId(state, name);
1398
           String[] csvLine = new String[table.getSize()];
1399
            for (SpecimenTypeDesignation specimenType: typeDesignations){
1400
                csvLine = new String[table.getSize()];
1401
                DerivedUnit specimen = specimenType.getTypeSpecimen();
1402
                if (state.getSpecimenFromStore(specimen.getId()) == null){
1403
                    handleSpecimen(state, specimen);
1404
                }
1405
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1406
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
1407
                csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] = specimenType.getTypeSpecimen().generateTitle();
1408
                //TODO: add link to existing Vorcabulary
1409
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
1410
                csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] = specimenType.getCitation().getTitleCache();
1411
                csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = getId(state, specimenType.getCitation());
1412
            }
1413
        } catch (Exception e) {
1414
            state.getResult().addException(e, "An unexpected error occurred when handling specimen type designations for " +
1415
                    cdmBaseStr(name) + ": " + e.getMessage());
1416
        }
1417
    }
1418

    
1419
    /**
1420
     * @param state
1421
     * @param specimen
1422
     */
1423
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase specimen) {
1424
        try {
1425
            state.addSpecimenToStore(specimen);
1426
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
1427
            String specimenId = getId(state, specimen);
1428
            String[] csvLine = new String[table.getSize()];
1429

    
1430
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
1431
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
1432
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractURIs(state, specimen.getDescriptions(), Feature.IMAGE());
1433
            if (specimen instanceof DerivedUnit){
1434
                    DerivedUnit derivedUnit = (DerivedUnit)specimen;
1435
                    if (derivedUnit.getCollection() != null){ csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection().getCode();}
1436

    
1437
                if (specimen instanceof MediaSpecimen){
1438
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
1439
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
1440
                    String mediaUris = extractMediaUris(it);
1441
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
1442

    
1443
                }
1444

    
1445
                if (derivedUnit.getDerivedFrom() != null){
1446
                    for (SpecimenOrObservationBase<?> original: derivedUnit.getDerivedFrom().getOriginals()){
1447
                        //TODO: What to do if there are more then one FieldUnit??
1448
                        if (original instanceof FieldUnit){
1449
                            FieldUnit fieldUnit = (FieldUnit)original;
1450
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
1451

    
1452
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
1453
                            if (gathering != null){
1454
                                if (gathering.getLocality() != null){ csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality().getText();}
1455
                                if (gathering.getCountry() != null){csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry().getLabel();}
1456
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(state, gathering, fieldUnit);
1457
                                addCollectingAreas(state, gathering);
1458
                                if (gathering.getGatheringDate() != null){csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering.getGatheringDate().toString();}
1459
                                if (!gathering.getCollectingAreas().isEmpty()){
1460
                                    int index = 0;
1461
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
1462
                                    for (NamedArea area: gathering.getCollectingAreas()){
1463
                                        if (index == 0){
1464
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getTermType().getKey();
1465
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
1466
                                        }
1467
                                        if (index == 1){
1468
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getTermType().getKey();
1469
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
1470
                                        }
1471
                                        if (index == 2){
1472
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getTermType().getKey();
1473
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
1474
                                        }
1475
                                        if (index == 3){
1476
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
1477
                                            break;
1478
                                        }
1479
                                        index++;
1480
                                    }
1481
                                }
1482
                            }
1483
                        }
1484
                    }
1485
                }
1486
            }
1487

    
1488
            state.getProcessor().put(table, specimen, csvLine);
1489
        } catch (Exception e) {
1490
            state.getResult().addException(e, "An unexpected error occurred when handling specimen " +
1491
                    cdmBaseStr(specimen) + ": " + e.getMessage());
1492
        }
1493
    }
1494

    
1495
    /**
1496
     * @param it
1497
     */
1498
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
1499
        String mediaUriString = "";
1500
        boolean first = true;
1501
        while(it.hasNext()){
1502
            MediaRepresentation rep = it.next();
1503
            List<MediaRepresentationPart> parts = rep.getParts();
1504
            for (MediaRepresentationPart part: parts){
1505
                if (first){
1506
                    if (part.getUri() != null){
1507
                        mediaUriString += part.getUri().toString();
1508
                        first = false;
1509
                    }
1510
                }else{
1511
                    if (part.getUri() != null){
1512
                        mediaUriString += ", " +part.getUri().toString();
1513
                    }
1514
                }
1515
            }
1516
        }
1517
        return mediaUriString;
1518
    }
1519

    
1520
    /**
1521
     * @param state
1522
     * @param gathering
1523
     */
1524
    private void addCollectingAreas(CdmLightExportState state, GatheringEvent gathering) {
1525
        // TODO implement !!!
1526

    
1527
        if (!gathering.getCollectingAreas().isEmpty()){
1528
            state.getResult().addWarning("Collecting areas not yet implemented but gathering " +
1529
                    cdmBaseStr(gathering) + " has collecting areas.");
1530
        }
1531

    
1532
    }
1533

    
1534
    /**
1535
     * @param gathering
1536
     * @return
1537
     */
1538
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
1539
        try {
1540
            String collectorString = "";
1541
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
1542
            if (gathering.getCollector() != null){
1543
               if (collectorA instanceof TeamOrPersonBase
1544
                       && state.getConfig().isHighLightPrimaryCollector()){
1545

    
1546
                   Person primaryCollector = fieldUnit.getPrimaryCollector();
1547
                   if (collectorA instanceof Team){
1548
                       Team collectorTeam = (Team)collectorA;
1549
                       boolean isFirst = true;
1550
                       for (Person member: collectorTeam.getTeamMembers()){
1551
                           if (!isFirst){
1552
                               collectorString += "; ";
1553
                           }
1554
                           if (member.equals(primaryCollector)){
1555
                               //highlight
1556
                               collectorString += "<b>" + member.getTitleCache() + "</b>";
1557
                           }else{
1558
                               collectorString += member.getTitleCache();
1559
                           }
1560
                       }
1561
                   }
1562
               } else{
1563
                   collectorString = collectorA.getTitleCache();
1564
               }
1565
           }
1566
           return collectorString;
1567
        } catch (Exception e) {
1568
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for " +
1569
                    cdmBaseStr(fieldUnit) + ": " + e.getMessage());
1570
            return "";
1571
        }
1572
    }
1573

    
1574

    
1575
    /**
1576
     * Returns a string representation of the {@link CdmBase cdmBase} object
1577
     * for result messages.
1578
     */
1579
    private String cdmBaseStr(CdmBase cdmBase) {
1580
        if (cdmBase == null){
1581
            return "-no object available-";
1582
        }else{
1583
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
1584
        }
1585
    }
1586

    
1587
    /**
1588
     * {@inheritDoc}
1589
     */
1590
    @Override
1591
    protected boolean doCheck(CdmLightExportState state) {
1592
        return false;
1593
    }
1594

    
1595
    /**
1596
     * {@inheritDoc}
1597
     */
1598
    @Override
1599
    protected boolean isIgnore(CdmLightExportState state) {
1600
        return false;
1601
    }
1602

    
1603
}
(1-1/5)