Project

General

Profile

Download (80.1 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

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

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

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

    
89

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

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

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

    
102
    }
103

    
104
    /**
105
     * {@inheritDoc}
106
     */
107
    @Override
108
    protected void doInvoke(CdmLightExportState state) {
109
        try {
110

    
111
            IProgressMonitor monitor = state.getConfig().getProgressMonitor();
112
            CdmLightExportConfigurator config = state.getConfig();
113
            config.setFieldsTerminatedBy(",");
114

    
115
//            if (config.getTaxonNodeFilter().getTaxonNodesFilter().isEmpty() && config.getTaxonNodeFilter().getClassificationFilter().isEmpty()){
116
//                //TODO
117
//                state.setEmptyData();
118
//                return;
119
//            }
120

    
121

    
122

    
123
//            for (LogicFilter<Classification> classificationFilter : config.getTaxonNodeFilter().getClassificationFilter()){
124
//                UUID classificationUuid = classificationFilter.getUuid();
125
//                Classification classification = getClassificationService().find(classificationUuid);
126
//                if (classification == null){
127
//                    String message = String.format("Classification for given classification UUID not found. No data imported for %s", classificationUuid.toString());
128
//                    state.getResult().addWarning(message);
129
//                }else{
130
//                    TaxonNode root = classification.getRootNode();
131
//                    UUID uuid = root.getUuid();
132
//                    root = getTaxonNodeService().load(uuid);
133
//                    handleSingleClassification(state, root.getUuid());
134
//                }
135
//            }
136

    
137

    
138
            @SuppressWarnings("unchecked")
139
            TaxonNodeOutStreamPartitioner<XmlExportState> partitioner
140
              = TaxonNodeOutStreamPartitioner.NewInstance(
141
                    this, state, state.getConfig().getTaxonNodeFilter(),
142
                    100, monitor, null);
143

    
144

    
145
                monitor.subTask("Start partitioning");
146

    
147
                TaxonNode node = partitioner.next();
148
                while (node != null){
149
                  handleTaxonNode(state, node);
150
                  node = partitioner.next();
151
                }
152

    
153

    
154
//            for (LogicFilter<TaxonNode> taxonNodeFilter : config.getTaxonNodeFilter().getTaxonNodesFilter()){
155
//                UUID nodeUuid = taxonNodeFilter.getUuid();
156
//                handleSingleClassification(state, nodeUuid);
157
//            }
158
            state.getProcessor().createFinalResult(state);
159
        } catch (Exception e) {
160
            state.getResult().addException(e, "An unexpected error occurred in main method doInvoke() " +
161
                    e.getMessage());
162
        }
163
    }
164

    
165
    /**
166
     * @param state
167
     * @param classificationUuid
168
     */
169
    private void handleTaxonNode(CdmLightExportState state, TaxonNode taxonNode) {
170
        try {
171
//            TaxonNode taxonNode = getTaxonNodeService().find(taxonNodeUuid);
172

    
173
            if (taxonNode == null){
174
                String message = "TaxonNode for given taxon node UUID not found. ";
175
                //TODO
176
                state.getResult().addWarning(message);
177
            }else{
178
                TaxonNode root = taxonNode;
179
                if (root.hasTaxon()){
180
                    handleTaxon(state, root);
181
                }else{
182
//                    for (TaxonNode child : root.getChildNodes()){
183
//                        handleTaxon(state, child);
184
//                        //TODO progress monitor
185
//                    }
186
                }
187
            }
188
        } catch (Exception e) {
189
            state.getResult().addException(e, "An unexpected error occurred when handling classification " +
190
                    taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
191
        }
192
    }
193

    
194
    /**
195
     * @param state
196
     * @param taxon
197
     */
198
    private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
199
        try{
200
      //  Taxon taxon = taxonNode.getTaxon();
201
        if (taxonNode == null){
202
            state.getResult().addError ("The taxonNode was null.", "handleTaxon");
203
            state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
204
            return;
205
        }
206
        if (taxonNode.getTaxon() == null){
207
            state.getResult().addError ("There was a taxon node without a taxon: " + taxonNode.getUuid(), "handleTaxon");
208
            state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
209
        }else{
210
            Taxon taxon = taxonNode.getTaxon();
211
             try{
212
                TaxonName name = taxon.getName();
213
                handleName(state, name);
214
                for (Synonym syn : taxon.getSynonyms()){
215
                    handleSynonym(state, syn);
216
                }
217

    
218

    
219
                CdmLightExportTable table = CdmLightExportTable.TAXON;
220
                String[] csvLine = new String[table.getSize()];
221

    
222
                csvLine[table.getIndex(CdmLightExportTable.TAXON_ID)] = getId(state, taxon);
223
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
224
                Taxon parent = (taxonNode.getParent()==null) ? null : taxonNode.getParent().getTaxon();
225
                csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
226
                csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
227
                csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(taxon.getSec());
228
                csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state, taxonNode.getClassification());
229
                csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification().getTitleCache();
230

    
231
                state.getProcessor().put(table, taxon, csvLine);
232
                handleDescriptions(state, taxon);
233
             }catch(Exception e){
234
                 state.getResult().addException (e, "An unexpected problem occurred when trying to export "
235
                         + "taxon with id " + taxon.getId());
236
                 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
237
             }
238
       }
239

    
240
       taxonNode.removeNullValueFromChildren();
241
//       for (TaxonNode child: taxonNode.getChildNodes()){
242
//           handleTaxon(state, child);
243
//       }
244
        }catch (Exception e){
245
            state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of " +
246
                    cdmBaseStr(taxonNode.getTaxon()) + ": " + e.getMessage());
247
        }
248
    }
249

    
250
    /**
251
     * @param state
252
     * @param taxon
253
     */
254
    private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
255
        try{
256
        if (cdmBase instanceof Taxon){
257
            Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
258
            Set<TaxonDescription> descriptions = taxon.getDescriptions();
259
            List<DescriptionElementBase> simpleFacts = new ArrayList<>();
260
            List<DescriptionElementBase> specimenFacts = new ArrayList<>();
261
            List<DescriptionElementBase> distributionFacts = new ArrayList<>();
262
            List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
263
            List<DescriptionElementBase> usageFacts = new ArrayList<>();
264
            for (TaxonDescription description: descriptions){
265
                if (description.getElements() != null){
266
                    for (DescriptionElementBase element: description.getElements()){
267
                        element = CdmBase.deproxy(element);
268
                        if (element.getFeature().equals(Feature.COMMON_NAME())){
269
                            commonNameFacts.add(element);
270
                        }else if (element.getFeature().equals(Feature.DISTRIBUTION())){
271
                            distributionFacts.add(element);
272
                        }else if (element instanceof IndividualsAssociation || isSpecimenFeature(element.getFeature())){
273
                            specimenFacts.add(element);
274
                        }else{
275
                            simpleFacts.add(element);
276
                        }
277
                    }
278
                }
279
            }
280
            if (!commonNameFacts.isEmpty()){
281
                handleCommonNameFacts(state, taxon, commonNameFacts);
282
            }
283
            if (!distributionFacts.isEmpty()){
284
                handleDistributionFacts(state, taxon, distributionFacts);
285
            }
286
            if (!specimenFacts.isEmpty()){
287
                handleSpecimenFacts(state, taxon, specimenFacts);
288
            }
289
            if (!simpleFacts.isEmpty()){
290
                handleSimpleFacts(state, taxon, simpleFacts);
291
            }
292
        } else if (cdmBase instanceof TaxonName){
293
            TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
294
            Set<TaxonNameDescription> descriptions = name.getDescriptions();
295
            List<DescriptionElementBase> simpleFacts = new ArrayList<>();
296
            for (TaxonNameDescription description: descriptions){
297
                if (description.getElements() != null){
298
                    for (DescriptionElementBase element: description.getElements()){
299
                        if (!element.getFeature().equals(Feature.PROTOLOGUE())){
300
                            simpleFacts.add(element);
301
                        }
302
                    }
303
                }
304
             }
305
            if (!simpleFacts.isEmpty()){
306
                handleSimpleFacts(state, name, simpleFacts);
307
            }
308
        }
309
        }catch (Exception e){
310
            state.getResult().addException(e, "An unexpected error occurred when handling description of" +
311
                    cdmBaseStr(cdmBase) + ": " + e.getMessage());
312
        }
313
    }
314

    
315

    
316
    /**
317
     * @param feature
318
     * @return
319
     */
320
    private boolean isSpecimenFeature(Feature feature) {
321
        //TODO allow user defined specimen features
322
        if (feature == null){
323
            return false;
324
        }else if (feature.isSupportsIndividualAssociation()){
325
            return true;
326
        }else{
327
            return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
328
                    || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
329
                    || feature.equals(Feature.OCCURRENCE())
330
                     ;
331
        }
332
    }
333

    
334
    /**
335
     * @param state
336
     * @param taxon
337
     * @param simpleFacts
338
     */
339
    private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
340
            List<DescriptionElementBase> simpleFacts) {
341
        try {
342
            CdmLightExportTable table = CdmLightExportTable.SIMPLE_FACT;
343
            CdmLightExportTable tableMedia = CdmLightExportTable.MEDIA;
344
            for (DescriptionElementBase element: simpleFacts){
345
                if (element.getModifyingText().isEmpty() && !element.getMedia().isEmpty()){
346
                    handleSimpleMediaFact(state, cdmBase, tableMedia, element);
347
                }else{
348
                    handleSingleSimpleFact(state, cdmBase, table, element);
349
                }
350
            }
351
        } catch (Exception e) {
352
            state.getResult().addException(e, "An unexpected error occurred when handling simple facts for " +
353
                    cdmBaseStr(cdmBase) + ": " + e.getMessage());
354
        }
355
    }
356

    
357
    /**
358
     * @param state
359
     * @param cdmBase
360
     * @param tableMedia
361
     * @param element
362
     */
363
    private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
364
            DescriptionElementBase element) {
365
        try {
366
            String[] csvLine;
367
            handleSource(state, element, CdmLightExportTable.MEDIA);
368

    
369
            if (element instanceof TextData){
370
               TextData textData = (TextData)element;
371
               csvLine = new String[table.getSize()];
372
               csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
373
               if (cdmBase instanceof Taxon){
374
                   csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
375
                   csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
376
               }else if (cdmBase instanceof TaxonName){
377
                   csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
378
                   csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
379
               }
380

    
381

    
382
               String mediaUris = "";
383
               for (Media media: textData.getMedia()){
384
                   String mediaString = extractMediaUris(media.getRepresentations().iterator());
385
                   if (!StringUtils.isBlank(mediaString)){
386
                       mediaUris +=  mediaString + ";";
387
                   }
388
                   else{
389
                       state.getResult().addWarning("Empty Media object for "
390
                               + cdmBase.getUserFriendlyTypeName() + " " + cdmBase.getUuid()
391
                               + " (media: " + media.getUuid() + ")");
392
                   }
393
               }
394
               csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
395

    
396
            }
397
        } catch (Exception e) {
398
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact " +
399
                    cdmBaseStr(element) + ": " + e.getMessage());
400
        }
401

    
402
    }
403

    
404
    /**
405
     * @param state
406
     * @param cdmBase
407
     * @param table
408
     * @param element
409
     */
410
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
411
            DescriptionElementBase element) {
412
        try {
413
            String[] csvLine;
414
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
415

    
416
            if (element instanceof TextData){
417
               TextData textData = (TextData)element;
418
               csvLine = new String[table.getSize()];
419
               csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
420
               if (cdmBase instanceof Taxon){
421
                   csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
422
                   csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
423
               }else if (cdmBase instanceof TaxonName){
424
                   csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
425
                   csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
426
               }
427
               csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
428

    
429
               String mediaUris = "";
430
               for (Media media: textData.getMedia()){
431
                   String mediaString = extractMediaUris(media.getRepresentations().iterator());
432
                   if (!StringUtils.isBlank(mediaString)){
433
                       mediaUris +=  mediaString + ";";
434
                   }
435
                   else{
436
                       state.getResult().addWarning("Empty Media object for uuid: " +
437
                               cdmBase.getUuid() + " uuid of media: " + media.getUuid());
438
                   }
439
               }
440
               csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
441
               if (textData.getFeature().equals(Feature.CITATION())){
442
                  // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
443
                   state.getProcessor().put(table, textData, csvLine);
444
               }else if (!textData.getMultilanguageText().isEmpty()){
445
                   for (Language language: textData.getMultilanguageText().keySet()){
446
                       String[] csvLineLanguage = csvLine.clone();
447
                       LanguageString langString = textData.getLanguageText(language);
448

    
449
                       csvLineLanguage[table.getIndex(CdmLightExportTable.FACT_TEXT)] = langString.getText();
450
                       csvLineLanguage[table.getIndex(CdmLightExportTable.LANGUAGE)] = language.getLabel();
451
                       state.getProcessor().put(table, textData, csvLineLanguage);
452
                   }
453
               } else{
454
                   state.getProcessor().put(table, textData, csvLine);
455
               }
456
            }
457
        } catch (Exception e) {
458
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact " +
459
                    cdmBaseStr(element) + ": " + e.getMessage());
460
        }
461
    }
462

    
463

    
464
    /**
465
     * @param state
466
     * @param specimenFacts
467
     */
468
    private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> specimenFacts) {
469
        CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
470

    
471
        for (DescriptionElementBase element: specimenFacts){
472
            try {
473
                String[] csvLine = new String[table.getSize()];
474
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
475
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
476
                handleSource(state, element, table);
477
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(element.getAnnotations());
478

    
479
                if (element instanceof IndividualsAssociation){
480

    
481
                    IndividualsAssociation indAssociation = (IndividualsAssociation)element;
482
                    if (indAssociation.getAssociatedSpecimenOrObservation() == null){
483
                        state.getResult().addWarning("There is an individual association with no specimen associated (Taxon "+ taxon.getTitleCache() + "(" + taxon.getUuid() +"). Could not be exported.");
484
                        continue;
485
                    }else{
486
                        if (state.getSpecimenFromStore(indAssociation.getAssociatedSpecimenOrObservation().getId()) == null){
487
                            SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(indAssociation.getAssociatedSpecimenOrObservation());
488

    
489
                            if (specimenBase instanceof SpecimenOrObservationBase){
490
                                SpecimenOrObservationBase derivedUnit = specimenBase;
491
                                handleSpecimen(state, derivedUnit);
492
                                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, indAssociation.getAssociatedSpecimenOrObservation());
493
                            }else{
494
                                //field units are not supported
495
                                state.getResult().addError("The associated Specimen of taxon " + taxon.getUuid() + " is not an DerivedUnit. Could not be exported.");
496

    
497
                            }
498
                        }
499
                    }
500
                } else if (element instanceof TextData){
501
                    TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
502
                    csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(textData.getMultilanguageText());
503
                }
504
                state.getProcessor().put(table, element, csvLine);
505
            } catch (Exception e) {
506
                state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact " +
507
                        cdmBaseStr(element) + ": " + e.getMessage());
508
            }
509
        }
510
    }
511

    
512
    /**
513
     * @param multilanguageText
514
     * @return
515
     */
516
    private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
517
       String text = "";
518
       int index = multilanguageText.size();
519
       for(LanguageString langString: multilanguageText.values()){
520
           text += langString.getText();
521
           if (index > 1){
522
               text += "; ";
523
           }
524
           index --;
525
       }
526

    
527
        return text;
528
    }
529

    
530
    /**
531
     * @param annotations
532
     * @return
533
     */
534
    private String createAnnotationsString(Set<Annotation> annotations) {
535
        StringBuffer strBuff = new StringBuffer();
536

    
537
        for (Annotation ann:annotations){
538
            if (ann.getAnnotationType() == null ||!ann.getAnnotationType().equals(AnnotationType.TECHNICAL())){
539
                strBuff.append(ann.getText());
540
                strBuff.append("; ");
541
            }
542
        }
543

    
544
        if (strBuff.length() > 2){
545
            return strBuff.substring(0, strBuff.length()-2);
546
        }else{
547
            return null;
548
        }
549
    }
550

    
551
    /**
552
     * @param state
553
     * @param taxon
554
     * @param element
555
     */
556
    private void handleSource(CdmLightExportState state, DescriptionElementBase element, CdmLightExportTable factsTable) {
557
        CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
558
        try {
559
        Set<DescriptionElementSource> sources = element.getSources();
560

    
561
        for (DescriptionElementSource source: sources){
562

    
563
                String[] csvLine = new  String[table.getSize()];
564
                Reference ref = source.getCitation();
565
                if ((ref == null) && (source.getNameUsedInSource() == null)){
566
                    continue;
567
                }
568
                if (ref != null){
569
                    if (state.getReferenceFromStore(ref.getId()) == null){
570
                        handleReference(state, ref);
571

    
572
                    }
573
                    csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
574
                }
575
                csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
576

    
577
                csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state, source.getNameUsedInSource());
578
                csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
579
                if ( StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])  && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])){
580
                    continue;
581
                }
582
                state.getProcessor().put(table, source, csvLine);
583

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

    
590
    }
591

    
592
    /**
593
     * @param state
594
     * @param distributionFacts
595
     */
596
    private void handleDistributionFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> distributionFacts) {
597
        CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
598

    
599
        for (DescriptionElementBase element: distributionFacts){
600
            try {
601
                if (element instanceof Distribution){
602
                    String[] csvLine = new  String[table.getSize()];
603
                    Distribution distribution = (Distribution)element;
604
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
605
                    handleSource(state, element, table);
606
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
607
                    if (distribution.getArea() != null){
608
                        csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = distribution.getArea().getLabel();
609
                    }
610
                    if (distribution.getStatus() != null){
611
                        csvLine[table.getIndex(CdmLightExportTable.STATUS_LABEL)] = distribution.getStatus().getLabel();
612
                    }
613
                    state.getProcessor().put(table, distribution, csvLine);
614
                } else{
615
                    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());
616
                }
617
            } catch (Exception e) {
618
                state.getResult().addException(e, "An unexpected error occurred when handling single distribution " +
619
                        cdmBaseStr(element) + ": " + e.getMessage());
620
            }
621
        }
622
    }
623

    
624
    /**
625
     * @param state
626
     * @param commonNameFacts
627
     */
628
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> commonNameFacts) {
629
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
630

    
631
        for (DescriptionElementBase element: commonNameFacts){
632
            try {
633
                if (element instanceof CommonTaxonName){
634
                    String[] csvLine = new  String[table.getSize()];
635
                    CommonTaxonName commonName = (CommonTaxonName)element;
636
                    csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
637
                    handleSource(state, element, table);
638
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
639
                    if (commonName.getName() != null){csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();}
640
                    if (commonName.getLanguage() != null){csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();}
641
                    if (commonName.getArea() != null){ csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();}
642
                    state.getProcessor().put(table, commonName, csvLine);
643
                } else{
644
                    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());
645
                }
646
            } catch (Exception e) {
647
                state.getResult().addException(e, "An unexpected error occurred when handling single common name " +
648
                        cdmBaseStr(element) + ": " + e.getMessage());
649
            }
650
        }
651
    }
652

    
653
    /**
654
     * @param sec
655
     * @return
656
     */
657
    private String getTitleCache(IIdentifiableEntity identEntity) {
658
        if (identEntity == null){
659
            return "";
660
        }
661
        //TODO refresh?
662
        return identEntity.getTitleCache();
663
    }
664

    
665
    /**
666
     * @param state
667
     * @param taxon
668
     * @return
669
     */
670
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
671
        if (cdmBase == null){
672
            return "";
673
        }
674
        //TODO make configurable
675
        return cdmBase.getUuid().toString();
676
    }
677

    
678
    /**
679
     * @param state
680
     * @param syn
681
     */
682
    private void handleSynonym(CdmLightExportState state, Synonym syn) {
683
       try {
684

    
685
           TaxonName name = syn.getName();
686
           handleName(state, name);
687

    
688
           CdmLightExportTable table = CdmLightExportTable.SYNONYM;
689
           String[] csvLine = new String[table.getSize()];
690

    
691
           csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, syn);
692
           csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, syn.getAcceptedTaxon());
693
           csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
694
           csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, syn.getSec());
695
           csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(syn.getSec());
696

    
697
           state.getProcessor().put(table, syn, csvLine);
698
        } catch (Exception e) {
699
            state.getResult().addException(e, "An unexpected error occurred when handling synonym " +
700
                    cdmBaseStr(syn) + ": " + e.getMessage());
701
        }
702
    }
703

    
704
    /**
705
     * @param state
706
     * @param name
707
     */
708
    private void handleName(CdmLightExportState state, TaxonName name) {
709
        if (name == null){
710
            return;
711
        }
712
        try {
713
            Rank rank = name.getRank();
714
            CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
715
            name = HibernateProxyHelper.deproxy(name);
716
            String[] csvLine = new String[table.getSize()];
717

    
718
            csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
719
            if (name.getLsid() != null){
720
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
721
            }else{
722
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
723
            }
724

    
725
            handleIdentifier(state, name);
726
            handleDescriptions(state, name);
727

    
728
            csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
729
            if (rank != null){
730
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
731
                if (rank.isInfraGeneric()){
732
                    try {
733
                        csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank().getInfraGenericMarker();
734
                    } catch (UnknownCdmTypeException e) {
735
                        state.getResult().addError("Infrageneric marker expected but not available for rank " + name.getRank().getTitleCache());
736
                    }
737
                }
738
                if (rank.isInfraSpecific()){
739
                    csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
740
                }
741
            }else{
742
                csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
743
            }
744
            if (name.isProtectedTitleCache()){
745
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] =name.getTitleCache();
746
            }else{
747
                //TODO: adapt the tropicos titlecache creation
748
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
749
            }
750
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
751
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
752

    
753
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
754
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
755

    
756
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
757
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state,name.getBasionymAuthorship());
758
            if (name.getBasionymAuthorship() != null){
759
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
760
                    handleAuthor(state, name.getBasionymAuthorship());
761
                }
762
            }
763
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state, name.getExBasionymAuthorship());
764
            if (name.getExBasionymAuthorship() != null){
765
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
766
                    handleAuthor(state, name.getExBasionymAuthorship());
767
                }
768

    
769
            }
770
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,name.getCombinationAuthorship());
771
            if (name.getCombinationAuthorship() != null){
772
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
773
                    handleAuthor(state, name.getCombinationAuthorship());
774
                }
775
            }
776
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state, name.getExCombinationAuthorship());
777
            if (name.getExCombinationAuthorship() != null){
778
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
779
                    handleAuthor(state, name.getExCombinationAuthorship());
780
                }
781

    
782
            }
783

    
784
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
785

    
786
            Reference nomRef = (Reference)name.getNomenclaturalReference();
787

    
788
            if (nomRef != null){
789
                if (state.getReferenceFromStore(nomRef.getId()) == null){
790
                    handleReference(state, nomRef);
791
                }
792
                csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
793
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
794
                if (nomRef.getVolume() != null){
795
                    csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
796
                    csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
797
                }
798
                if (nomRef.getDatePublished() != null){
799
                    csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
800
                    csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
801
                    csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = null;
802
                }
803
                if (name.getNomenclaturalMicroReference() != null){
804
                    csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
805
                }
806
                nomRef = HibernateProxyHelper.deproxy(nomRef);
807
                if (nomRef.getInReference() != null){
808
                    Reference inReference = nomRef.getInReference();
809
                    if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null){
810
                        csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference.getDatePublishedString();
811
                        csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished().getYear();
812
                    }
813
                    if (nomRef.getVolume() == null && inReference.getVolume() != null){
814
                        csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
815
                        csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
816
                    }
817
                    if (inReference.getInReference() != null){
818
                        inReference = inReference.getInReference();
819
                    }
820
                    if (inReference.getAbbrevTitle() == null){
821
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(inReference.getAbbrevTitleCache());
822
                    }else{
823
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(inReference.getAbbrevTitle());
824
                    }
825
                    if (inReference.getTitle() == null){
826
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitleCache());
827
                    }else{
828
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
829
                    }
830

    
831

    
832
                    TeamOrPersonBase<?> author = inReference.getAuthorship();
833
                    if (author != null && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))){
834
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = CdmUtils.Nz(author.getNomenclaturalTitle());
835
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils.Nz(author.getTitleCache());
836
                    }else{
837
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
838
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
839
                    }
840
                }else{
841
                    if (nomRef.getAbbrevTitle() == null){
842
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(nomRef.getAbbrevTitleCache());
843
                    }else{
844
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(nomRef.getAbbrevTitle());
845
                    }
846
                    if (nomRef.getTitle() == null){
847
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitleCache());
848
                    }else{
849
                        csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
850
                    }
851
                    TeamOrPersonBase<?> author = nomRef.getAuthorship();
852
                    if (author != null ){
853
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = CdmUtils.Nz(author.getNomenclaturalTitle());
854
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils.Nz(author.getTitleCache());
855
                    }else{
856
                        csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
857
                        csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
858
                    }
859

    
860
                }
861
            }else{
862
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
863
            }
864

    
865

    
866

    
867
            /*
868
            * Collation
869

    
870
            Detail
871

    
872

    
873
            TitlePageYear
874
            */
875
            Set<TaxonNameDescription> descriptions = name.getDescriptions();
876
            String protologueUriString = extractURIs(state, descriptions, Feature.PROTOLOGUE());
877

    
878
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
879

    
880
            if (name.getStatus() == null || name.getStatus().isEmpty()){
881
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
882
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
883
            }else{
884

    
885
                String statusStringAbbrev = extractStatusString(state, name, true);
886
                String statusString = extractStatusString(state, name, false);
887

    
888
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
889
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
890
            }
891

    
892
            HomotypicalGroup group =name.getHomotypicalGroup();
893

    
894
            if (state.getHomotypicalGroupFromStore(group.getId()) == null){
895
                handleHomotypicalGroup(state, group);
896
            }
897
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
898
            List<TaxonName> typifiedNames = new ArrayList<>();
899
            typifiedNames.addAll(group.getTypifiedNames());
900
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
901
            Integer  seqNumber= typifiedNames.indexOf(name);
902
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
903
            state.getProcessor().put(table, name, csvLine);
904

    
905
            /*
906
             *
907
            Tropicos_ID
908
            IPNI_ID
909

    
910

    
911
            InfragenericRank
912

    
913

    
914
            InfraspecificRank
915
            Collation
916
            Volume (Issue)
917
            Detail
918
            DatePublished
919
            YearPublished
920
            TitlePageYear
921

    
922

    
923

    
924
            HomotypicGroupSequenceNumber
925

    
926

    
927
             *
928
             */
929
        } catch (Exception e) {
930
            state.getResult().addException(e, "An unexpected error occurred when handling synonym " +
931
                    cdmBaseStr(name) + ": " + e.getMessage());
932
        }
933
    }
934

    
935
    /**
936
     * @return
937
     */
938
    private String createCollatation(TaxonName name) {
939
        String collation = "";
940
        if (name.getNomenclaturalReference() != null){
941
            Reference ref = (Reference) name.getNomenclaturalReference();
942
            collation = getVolume(ref);
943
        }
944
        if (name.getNomenclaturalMicroReference() != null){
945
            if (!StringUtils.isBlank(collation)){
946
                collation += ":";
947
            }
948
            collation +=name.getNomenclaturalMicroReference();
949
        }
950

    
951
        return collation;
952
    }
953

    
954
    /**
955
     * @param nomenclaturalReference
956
     * @return
957
     */
958
    private String getVolume(Reference reference) {
959
        if (reference.getVolume() != null){
960
            return reference.getVolume();
961
        }else if (reference.getInReference() != null){
962
            if (reference.getInReference().getVolume() != null){
963
                return reference.getInReference().getVolume();
964
            }
965
        }
966
        return null;
967
    }
968

    
969
    /**
970
     * @param state
971
     * @param name
972
     */
973
    private void handleIdentifier(CdmLightExportState state, TaxonName name) {
974
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
975
        String[] csvLine;
976
        try {
977
            Set<String>  IPNIidentifiers = name.getIdentifiers(DefinedTerm.IPNI_NAME_IDENTIFIER());
978
            Set<String>  tropicosIdentifiers = name.getIdentifiers(DefinedTerm.TROPICOS_NAME_IDENTIFIER());
979
            Set<String>  WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
980
            if (!IPNIidentifiers.isEmpty()){
981
                csvLine = new String[table.getSize()];
982
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
983
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
984
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(IPNIidentifiers);
985
                state.getProcessor().put(table, name, csvLine);
986
            }
987
            if (!tropicosIdentifiers.isEmpty()){
988
                csvLine = new String[table.getSize()];
989
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
990
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
991
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(tropicosIdentifiers);
992
                state.getProcessor().put(table, name, csvLine);
993
            }
994
            if (!WFOIdentifiers.isEmpty()){
995
                csvLine = new String[table.getSize()];
996
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
997
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
998
                csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(WFOIdentifiers);
999
                state.getProcessor().put(table, name, csvLine);
1000
            }
1001
        } catch (Exception e) {
1002
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for " +
1003
                    cdmBaseStr(name) + ": " + e.getMessage());
1004

    
1005
        }
1006
    }
1007

    
1008
    /**
1009
     * @param tropicosIdentifiers
1010
     */
1011
    private String extractIdentifier(Set<String> identifierSet) {
1012

    
1013
        String identifierString = "";
1014
        for (String identifier: identifierSet){
1015
            if (!StringUtils.isBlank(identifierString)){
1016
                identifierString += ", ";
1017
            }
1018
            identifierString += identifier;
1019
        }
1020

    
1021
        return identifierString;
1022
    }
1023

    
1024
    /**
1025
     * @param state
1026
     * @param descriptions
1027
     * @return
1028
     */
1029
    private String extractURIs(CdmLightExportState state,
1030
            Set<? extends DescriptionBase<?>> descriptionsSet, Feature feature) {
1031
        String mediaUriString = "";
1032
        SpecimenDescription specimenDescription;
1033
        TaxonDescription taxonDescription;
1034
        TaxonNameDescription nameDescription;
1035
        Set<DescriptionElementBase> elements = new HashSet<>();
1036
        for (DescriptionBase<?> description : descriptionsSet){
1037
            try {
1038
                if (!description.getElements().isEmpty()){
1039
                    if (description instanceof SpecimenDescription){
1040
                        specimenDescription = (SpecimenDescription)description;
1041
                        elements = specimenDescription.getElements();
1042
                    }else if (description instanceof TaxonDescription){
1043
                        taxonDescription = (TaxonDescription) description;
1044
                        elements = taxonDescription.getElements();
1045
                    } else if (description instanceof TaxonNameDescription){
1046
                        nameDescription = (TaxonNameDescription) description;
1047
                        elements = nameDescription.getElements();
1048
                    }
1049

    
1050
                    for (DescriptionElementBase element : elements){
1051
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1052
                        if (entityFeature.equals(feature)){
1053
                            if (!element.getMedia().isEmpty()){
1054
                                List<Media> media = element.getMedia();
1055
                                for (Media mediaElement: media){
1056
                                    Iterator<MediaRepresentation> it =  mediaElement.getRepresentations().iterator();
1057
                                    mediaUriString = extractMediaUris(it);
1058
                                }
1059
                            }
1060
                        }
1061
                    }
1062
                }
1063
            } catch (Exception e) {
1064
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for " +
1065
                        cdmBaseStr(description) + ": " + e.getMessage());
1066
            }
1067
        }
1068
        return mediaUriString;
1069
    }
1070

    
1071
    /**
1072
     * @param state
1073
     * @param basionymAuthorship
1074
     */
1075
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1076
        try {
1077
            if (state.getAuthorFromStore(author.getId()) != null){
1078
                return;
1079
            }
1080
            state.addAuthorToStore(author);
1081
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1082
            String[] csvLine = new String[table.getSize()];
1083
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1084
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
1085
            String[] csvLineMember = new String[table.getSize()];
1086
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1087
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.getNomenclaturalTitle();
1088
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1089
            author = HibernateProxyHelper.deproxy(author);
1090
            if (author instanceof Person){
1091
                Person authorPerson = (Person)author;
1092
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FIRST_NAME)] = authorPerson.getFirstname();
1093
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_LASTNAME)] = authorPerson.getLastname();
1094
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1095
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1096
            } else{
1097
                // create an entry in rel table and all members in author table, check whether the team members already in author table
1098

    
1099
                Team authorTeam = (Team)author;
1100
                int index = 0;
1101
                for (Person member: authorTeam.getTeamMembers()){
1102
                    csvLineRel = new String[tableAuthorRel.getSize()];
1103
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1104
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1105
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String.valueOf(index);
1106
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() +":" +member.getId(), csvLineRel);
1107

    
1108
                    if (state.getAuthorFromStore(member.getId()) == null){
1109
                        state.addAuthorToStore(member);
1110
                        csvLineMember = new String[table.getSize()];
1111
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1112
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member.getNomenclaturalTitle();
1113
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1114
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FIRST_NAME)] = member.getFirstname();
1115
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_LASTNAME)] = member.getLastname();
1116
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1117
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1118
                        state.getProcessor().put(table, member, csvLineMember);
1119
                    }
1120
                    index++;
1121

    
1122
                }
1123
            }
1124
            state.getProcessor().put(table, author, csvLine);
1125
        } catch (Exception e) {
1126
            state.getResult().addException(e, "An unexpected error occurred when handling author " +
1127
                    cdmBaseStr(author) + ": " + e.getMessage());
1128
        }
1129
    }
1130

    
1131
    /**
1132
     * @param state
1133
     * @param name
1134
     * @param statusString
1135
     * @return
1136
     */
1137
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1138
        try {
1139
            Set<NomenclaturalStatus> status = name.getStatus();
1140
            if (status.isEmpty()){
1141
                return "";
1142
            }
1143
            String statusString = "";
1144
            for (NomenclaturalStatus nameStatus: status){
1145
                if (nameStatus != null){
1146
                    if (abbrev){
1147
                        if (nameStatus.getType() != null){
1148
                            statusString += nameStatus.getType().getIdInVocabulary();
1149
                        }
1150
                    }else{
1151
                        if (nameStatus.getType() != null){
1152
                            statusString += nameStatus.getType().getTitleCache();
1153
                        }
1154
                    }
1155
                    if (!abbrev){
1156

    
1157
                        if (nameStatus.getRuleConsidered() != null && !StringUtils.isBlank(nameStatus.getRuleConsidered())){
1158
                            statusString += " " + nameStatus.getRuleConsidered();
1159
                        }
1160
                        if (nameStatus.getCitation() != null){
1161
                            statusString += " " + nameStatus.getCitation().getTitleCache();
1162
                        }
1163
                        if (nameStatus.getCitationMicroReference() != null && !StringUtils.isBlank(nameStatus.getCitationMicroReference())){
1164
                            statusString += " " + nameStatus.getCitationMicroReference();
1165
                        }
1166
                    }
1167
                    statusString += " ";
1168
                }
1169
            }
1170
            return statusString;
1171
        } catch (Exception e) {
1172
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for " +
1173
                    cdmBaseStr(name) + ": " + e.getMessage());
1174
            return "";
1175
        }
1176
    }
1177

    
1178
    /**
1179
     * @param group
1180
     */
1181
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group) {
1182
        try {
1183
            state.addHomotypicalGroupToStore(group);
1184
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1185
            String[] csvLine = new String[table.getSize()];
1186

    
1187
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1188
            List<TaxonName> typifiedNames = new ArrayList<>();
1189
            typifiedNames.addAll(group.getTypifiedNames());
1190
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1191
            String typifiedNamesString = "";
1192
            for (TaxonName name: typifiedNames){
1193
                //Concatenated output string for homotypic group (names and citations) + status + some name relations (e.g. “non”)
1194
                //TODO: nameRelations, which and how to display
1195

    
1196

    
1197
                typifiedNamesString += name.getTitleCache()+ extractStatusString(state, name, true) + "; ";
1198
            }
1199
            typifiedNamesString = typifiedNamesString.substring(0, typifiedNamesString.length()-2);
1200
            if (typifiedNamesString != null){
1201
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
1202
            }else{
1203
                csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
1204
            }
1205
            Set<TypeDesignationBase> typeDesigantions = group.getTypeDesignations();
1206
            List<TypeDesignationBase> designationList = new ArrayList<>();
1207
            designationList.addAll(typeDesigantions);
1208
            Collections.sort(designationList, new TypeComparator());
1209
            StringBuffer typeDesignationString = new StringBuffer();
1210
            for (TypeDesignationBase typeDesignation: typeDesigantions){
1211
                if (typeDesignation != null && typeDesignation.getTypeStatus() != null){
1212
                    typeDesignationString.append(typeDesignation.getTypeStatus().getTitleCache() + ": ");
1213
                }
1214
                if (typeDesignation instanceof SpecimenTypeDesignation){
1215
                    if (((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen() != null){
1216
                        typeDesignationString.append(((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen().getTitleCache());
1217
                        handleSpecimen(state, ((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen());
1218
                    }
1219
                }else{
1220
                    if (((NameTypeDesignation)typeDesignation).getTypeName() != null){
1221
                        typeDesignationString.append(((NameTypeDesignation)typeDesignation).getTypeName().getTitleCache());
1222
                    }
1223
                }
1224
                if(typeDesignation.getCitation() != null ){
1225
                    typeDesignationString.append(", "+typeDesignation.getCitation().getTitleCache());
1226
                }
1227
                //TODO...
1228
                /*
1229
                 * Sortierung:
1230
                1.  Status der Typen: a) holo, lecto, neo, syn, b) epi, paralecto, c) para (wenn überhaupt) – die jeweiligen iso immer direct mit dazu
1231
                2.  Land
1232
                3.  Sammler
1233
                4.  Nummer
1234

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

    
1238
                 */
1239
            }
1240
            String typeDesignations = typeDesignationString.toString();
1241
            if (typeDesignations != null){
1242
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = typeDesignations;
1243
            }else{
1244
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
1245
            }
1246
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
1247
        } catch (Exception e) {
1248
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group " +
1249
                    cdmBaseStr(group) + ": " + e.getMessage());
1250
        }
1251
    }
1252

    
1253
    /**
1254
     * @param name
1255
     * @return
1256
     */
1257
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
1258
        try {
1259
            String basionymStart = "(";
1260
            String basionymEnd = ") ";
1261
            String exAuthorSeperator = " ex ";
1262
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
1263
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
1264
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
1265
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
1266

    
1267
            String combinationAuthorString = "";
1268
            if (combinationAuthor != null){
1269
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
1270
                if (combinationAuthor instanceof Team){
1271
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
1272
                }else{
1273
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
1274
                    combinationAuthorString = createTropicosAuthorString(person);
1275
                }
1276
            }
1277
            String exCombinationAuthorString = "";
1278
            if (exCombinationAuthor != null){
1279
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
1280
                if (exCombinationAuthor instanceof Team){
1281
                   exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
1282
                }else{
1283
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
1284
                    exCombinationAuthorString = createTropicosAuthorString(person);
1285
                }
1286
            }
1287

    
1288
            String basionymAuthorString = "";
1289
            if (basionymAuthor != null){
1290
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
1291
                if (basionymAuthor instanceof Team){
1292
                    basionymAuthorString =  createTropicosTeamTitle(basionymAuthor);
1293
                }else{
1294
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
1295
                    basionymAuthorString = createTropicosAuthorString(person);
1296
                }
1297
            }
1298

    
1299
            String exBasionymAuthorString = "";
1300

    
1301
            if (exBasionymAuthor != null){
1302
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
1303
                if (exBasionymAuthor instanceof Team){
1304
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
1305

    
1306
                }else{
1307
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
1308
                    exBasionymAuthorString = createTropicosAuthorString(person);
1309
                }
1310
            }
1311
            String completeAuthorString =  name.getNameCache() + " ";
1312

    
1313
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString) || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart: "";
1314
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)) ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator): "" ;
1315
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString))? CdmUtils.Nz(basionymAuthorString):"";
1316
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString) || !CdmUtils.isBlank(basionymAuthorString)) ?  basionymEnd:"";
1317
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString)) ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator): "" ;
1318
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString))? CdmUtils.Nz(combinationAuthorString):"";
1319

    
1320

    
1321
            return completeAuthorString;
1322
        } catch (Exception e) {
1323
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for " +
1324
                    cdmBaseStr(name) + ": " + e.getMessage());
1325
            return null;
1326
        }
1327
    }
1328

    
1329
    /**
1330
     * @param combinationAuthor
1331
     * @return
1332
     */
1333
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
1334
        String combinationAuthorString;
1335
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
1336
        Team tempTeam = Team.NewInstance();
1337
        for (Person teamMember:team.getTeamMembers()){
1338
            combinationAuthorString = createTropicosAuthorString(teamMember);
1339
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
1340
            tempTeam.addTeamMember(tempPerson);
1341
        }
1342
        combinationAuthorString = tempTeam.generateTitle();
1343
        return combinationAuthorString;
1344
    }
1345

    
1346
    /**
1347
     * @param teamMember
1348
     */
1349
    private String createTropicosAuthorString(Person teamMember) {
1350
        String nomAuthorString = "";
1351
        String[] splittedAuthorString = null;
1352
        if (teamMember == null){
1353
            return nomAuthorString;
1354
        }
1355

    
1356
        if (teamMember.getFirstname() != null){
1357
            String firstNameString = teamMember.getFirstname().replaceAll("\\.", "\\. ");
1358
            splittedAuthorString = firstNameString.split("\\s");
1359
            for (String split: splittedAuthorString){
1360
                if (!StringUtils.isBlank(split)){
1361
                    nomAuthorString += split.substring(0, 1);
1362
                    nomAuthorString += ".";
1363
                }
1364
            }
1365
        }
1366
        if (teamMember.getLastname() != null){
1367
            String lastNameString = teamMember.getLastname().replaceAll("\\.", "\\. ");
1368
            splittedAuthorString = lastNameString.split("\\s");
1369
            for (String split: splittedAuthorString){
1370
                nomAuthorString += " " +split;
1371
            }
1372
        }
1373
        if (StringUtils.isBlank(nomAuthorString.trim())){
1374
            if (teamMember.getTitleCache() != null) {
1375
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
1376
                splittedAuthorString = titleCacheString.split("\\s");
1377
            }
1378

    
1379

    
1380
            int index = 0;
1381
            for (String split: splittedAuthorString){
1382
                if ( index < splittedAuthorString.length-1 && (split.length()==1 || split.endsWith("."))){
1383
                    nomAuthorString += split;
1384
                }else{
1385
                    nomAuthorString = nomAuthorString +" "+ split;
1386
                }
1387
                index++;
1388
            }
1389
        }
1390
        return nomAuthorString.trim();
1391
    }
1392

    
1393
    /**
1394
     * @param state
1395
     * @param name
1396
     */
1397
    private void handleReference(CdmLightExportState state, Reference reference) {
1398
        try {
1399
            state.addReferenceToStore(reference);
1400
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
1401

    
1402
            String[] csvLine = new String[table.getSize()];
1403
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
1404
            //TODO short citations correctly
1405
            String shortCitation = createShortCitation(reference);  //Should be Author(year) like in Taxon.sec
1406
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
1407
            //TODO get preferred title
1408
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.getTitle();
1409
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.getAbbrevTitle();
1410
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
1411
            //TBC
1412
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
1413
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
1414
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
1415
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
1416
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
1417
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
1418
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
1419
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
1420
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
1421
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
1422
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
1423
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
1424
            if ( reference.getAuthorship() != null){
1425
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = reference.getAuthorship().getTitleCache();
1426
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state,reference.getAuthorship());
1427
            }
1428

    
1429
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
1430
            if (reference.getInReference() != null && state.getReferenceFromStore(reference.getInReference().getId()) == null){
1431
                handleReference(state, reference.getInReference());
1432
            }
1433
            if ( reference.getInstitution() != null){ csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();}
1434
            if ( reference.getLsid() != null){ csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();}
1435
            if ( reference.getSchool() != null){ csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();}
1436
            if ( reference.getUri() != null){ csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();}
1437
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
1438

    
1439
            state.getProcessor().put(table, reference, csvLine);
1440
        } catch (Exception e) {
1441
            state.getResult().addException(e, "An unexpected error occurred when handling reference " +
1442
                    cdmBaseStr(reference) + ": " + e.getMessage());
1443
        }
1444

    
1445
    }
1446

    
1447

    
1448
    /**
1449
     * @param reference
1450
     * @return
1451
     */
1452
    private String createShortCitation(Reference reference) {
1453
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
1454
        String shortCitation = "";
1455
        if (authorship == null) {
1456
            return null;
1457
        }
1458
        authorship = HibernateProxyHelper.deproxy(authorship);
1459
        if (authorship instanceof Person){ shortCitation = ((Person)authorship).getLastname();}
1460
        else if (authorship instanceof Team){
1461

    
1462
            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
1463
            int index = 0;
1464

    
1465
            for (Person teamMember : authorTeam.getTeamMembers()){
1466
                index++;
1467
                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
1468
                shortCitation += concat + teamMember.getLastname();
1469
            }
1470

    
1471
        }
1472
        if (reference.getYear() != null){
1473
            shortCitation = shortCitation + " (" + reference.getYear() + ")";
1474
        }
1475
        return shortCitation;
1476
    }
1477

    
1478
    private static String concatString(Team team, List<Person> teamMembers, int i) {
1479
        String concat;
1480
        if (i <= 1){
1481
            concat = "";
1482
        }else if (i < teamMembers.size() || ( team.isHasMoreMembers() && i == teamMembers.size())){
1483
            concat = STD_TEAM_CONCATINATION;
1484
        }else{
1485
            concat = FINAL_TEAM_CONCATINATION;
1486
        }
1487
        return concat;
1488
    }
1489

    
1490
    /*
1491
     * TypeDesignation table
1492
     * Specimen_Fk
1493
     *  EditName_Fk
1494
     *   TypeVerbatimCitation
1495
     *   TypeCategory
1496
     *   TypeDesignatedByString
1497
     *   TypeDesignatedByRef_Fk
1498
     */
1499

    
1500
    private void handleSpecimenTypeDesignations(CdmLightExportState state, TaxonName name){
1501
       try {
1502
           Set<SpecimenTypeDesignation> typeDesignations = name.getSpecimenTypeDesignations();
1503
           CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1504
           String nameId = getId(state, name);
1505
           String[] csvLine = new String[table.getSize()];
1506
            for (SpecimenTypeDesignation specimenType: typeDesignations){
1507
                csvLine = new String[table.getSize()];
1508
                DerivedUnit specimen = specimenType.getTypeSpecimen();
1509
                if (state.getSpecimenFromStore(specimen.getId()) == null){
1510
                    handleSpecimen(state, specimen);
1511
                }
1512
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1513
                csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
1514
                csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] = specimenType.getTypeSpecimen().generateTitle();
1515
                //TODO: add link to existing Vorcabulary
1516
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
1517
                csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] = specimenType.getCitation().getTitleCache();
1518
                csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = getId(state, specimenType.getCitation());
1519
            }
1520
        } catch (Exception e) {
1521
            state.getResult().addException(e, "An unexpected error occurred when handling specimen type designations for " +
1522
                    cdmBaseStr(name) + ": " + e.getMessage());
1523
        }
1524
    }
1525

    
1526
    /**
1527
     * @param state
1528
     * @param specimen
1529
     */
1530
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase specimen) {
1531
        try {
1532
            state.addSpecimenToStore(specimen);
1533
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
1534
            String specimenId = getId(state, specimen);
1535
            String[] csvLine = new String[table.getSize()];
1536

    
1537
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
1538
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
1539
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractURIs(state, specimen.getDescriptions(), Feature.IMAGE());
1540
            if (specimen instanceof DerivedUnit){
1541
                    DerivedUnit derivedUnit = (DerivedUnit)specimen;
1542
                    if (derivedUnit.getCollection() != null){ csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection().getCode();}
1543

    
1544
                if (specimen instanceof MediaSpecimen){
1545
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
1546
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
1547
                    String mediaUris = extractMediaUris(it);
1548
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
1549

    
1550
                }
1551

    
1552
                if (derivedUnit.getDerivedFrom() != null){
1553
                    for (SpecimenOrObservationBase<?> original: derivedUnit.getDerivedFrom().getOriginals()){
1554
                        //TODO: What to do if there are more then one FieldUnit??
1555
                        if (original instanceof FieldUnit){
1556
                            FieldUnit fieldUnit = (FieldUnit)original;
1557
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
1558

    
1559
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
1560
                            if (gathering != null){
1561
                                if (gathering.getLocality() != null){ csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality().getText();}
1562
                                if (gathering.getCountry() != null){csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry().getLabel();}
1563
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(state, gathering, fieldUnit);
1564
                                addCollectingAreas(state, gathering);
1565
                                if (gathering.getGatheringDate() != null){csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering.getGatheringDate().toString();}
1566
                                if (!gathering.getCollectingAreas().isEmpty()){
1567
                                    int index = 0;
1568
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
1569
                                    for (NamedArea area: gathering.getCollectingAreas()){
1570
                                        if (index == 0){
1571
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getTermType().getKey();
1572
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
1573
                                        }
1574
                                        if (index == 1){
1575
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getTermType().getKey();
1576
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
1577
                                        }
1578
                                        if (index == 2){
1579
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getTermType().getKey();
1580
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
1581
                                        }
1582
                                        if (index == 3){
1583
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
1584
                                            break;
1585
                                        }
1586
                                        index++;
1587
                                    }
1588
                                }
1589
                            }
1590
                        }
1591
                    }
1592
                }
1593
            }
1594

    
1595
            state.getProcessor().put(table, specimen, csvLine);
1596
        } catch (Exception e) {
1597
            state.getResult().addException(e, "An unexpected error occurred when handling specimen " +
1598
                    cdmBaseStr(specimen) + ": " + e.getMessage());
1599
        }
1600
    }
1601

    
1602
    /**
1603
     * @param it
1604
     */
1605
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
1606

    
1607
        String mediaUriString = "";
1608
        boolean first = true;
1609
        while(it.hasNext()){
1610
            MediaRepresentation rep = it.next();
1611
            List<MediaRepresentationPart> parts = rep.getParts();
1612
            for (MediaRepresentationPart part: parts){
1613
                if (first){
1614
                    if (part.getUri() != null){
1615
                        mediaUriString += part.getUri().toString();
1616
                        first = false;
1617
                    }
1618
                }else{
1619
                    if (part.getUri() != null){
1620
                        mediaUriString += ", " +part.getUri().toString();
1621
                    }
1622
                }
1623
            }
1624
        }
1625

    
1626
        return mediaUriString;
1627
    }
1628

    
1629
    /**
1630
     * @param state
1631
     * @param gathering
1632
     */
1633
    private void addCollectingAreas(CdmLightExportState state, GatheringEvent gathering) {
1634
        // TODO implement !!!
1635

    
1636
        if (!gathering.getCollectingAreas().isEmpty()){
1637
            state.getResult().addWarning("Collecting areas not yet implemented but gathering " +
1638
                    cdmBaseStr(gathering) + " has collecting areas.");
1639
        }
1640

    
1641
    }
1642

    
1643
    /**
1644
     * @param gathering
1645
     * @return
1646
     */
1647
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
1648
        try {
1649
            String collectorString = "";
1650
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
1651
            if (gathering.getCollector() != null){
1652
               if (collectorA instanceof TeamOrPersonBase
1653
                       && state.getConfig().isHighLightPrimaryCollector()){
1654

    
1655
                   Person primaryCollector = fieldUnit.getPrimaryCollector();
1656
                   if (collectorA instanceof Team){
1657
                       Team collectorTeam = (Team)collectorA;
1658
                       boolean isFirst = true;
1659
                       for (Person member: collectorTeam.getTeamMembers()){
1660
                           if (!isFirst){
1661
                               collectorString += "; ";
1662
                           }
1663
                           if (member.equals(primaryCollector)){
1664
                               //highlight
1665
                               collectorString += "<b>" + member.getTitleCache() + "</b>";
1666
                           }else{
1667
                               collectorString += member.getTitleCache();
1668
                           }
1669
                       }
1670
                   }
1671
               } else{
1672
                   collectorString = collectorA.getTitleCache();
1673
               }
1674
           }
1675
           return collectorString;
1676
        } catch (Exception e) {
1677
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for " +
1678
                    cdmBaseStr(fieldUnit) + ": " + e.getMessage());
1679
            return "";
1680
        }
1681
    }
1682

    
1683

    
1684
    /**
1685
     * Returns a string representation of the {@link CdmBase cdmBase} object
1686
     * for result messages.
1687
     */
1688
    private String cdmBaseStr(CdmBase cdmBase) {
1689
        if (cdmBase == null){
1690
            return "-no object available-";
1691
        }else{
1692
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
1693
        }
1694
    }
1695

    
1696
    /**
1697
     * {@inheritDoc}
1698
     */
1699
    @Override
1700
    protected boolean doCheck(CdmLightExportState state) {
1701
        return false;
1702
    }
1703

    
1704
    /**
1705
     * {@inheritDoc}
1706
     */
1707
    @Override
1708
    protected boolean isIgnore(CdmLightExportState state) {
1709
        return false;
1710
    }
1711

    
1712
}
(1-1/5)