Project

General

Profile

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

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

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

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

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

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

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

    
118
    @Autowired
119
    IEditGeoService geoService;
120

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
303
                try {
304
                    TaxonName name = taxon.getName();
305
                    handleName(state, name, true);
306
                    for (Synonym syn : taxon.getSynonyms()) {
307
                        handleSynonym(state, syn);
308
                    }
309
                    for (TaxonRelationship rel : taxon.getProParteAndPartialSynonymRelations()) {
310
                        handleProPartePartialMisapplied(state, rel);
311
                    }
312
                    for (TaxonRelationship rel : taxon.getMisappliedNameRelations()) {
313
                        handleProPartePartialMisapplied(state, rel);
314
                    }
315

    
316
                    CdmLightExportTable table = CdmLightExportTable.TAXON;
317
                    String[] csvLine = new String[table.getSize()];
318

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

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

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

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

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

    
446
    private void handleAnnotations(DescriptionElementBase element) {
447
        // TODO Auto-generated method stub
448
    }
449

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

    
463
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
464
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
465
        csvLine[table.getIndex(CdmLightExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
466
        csvLine[table.getIndex(CdmLightExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
467
        csvLine[table.getIndex(CdmLightExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
468
        state.getProcessor().put(table, "", csvLine);
469
    }
470

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

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

    
507
    private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
508
            List<DescriptionElementBase> taxonInteractionsFacts) {
509
        CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
510
        for (DescriptionElementBase element : taxonInteractionsFacts) {
511
            try {
512

    
513
                String[] csvLine = new String[table.getSize()];
514

    
515
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
516
                handleSource(state, element, table);
517
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
518
                csvLine[table.getIndex(CdmLightExportTable.TAXON2_FK)] = getId(state,
519
                        ((TaxonInteraction) element).getTaxon2());
520
                csvLine[table.getIndex(CdmLightExportTable.DESCRIPTION)] = createMultilanguageString(
521
                        ((TaxonInteraction) element).getDescription());
522
                state.getProcessor().put(table, element, csvLine);
523

    
524
            } catch (Exception e) {
525
                state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
526
                        + cdmBaseStr(element) + ": " + e.getMessage());
527
            }
528
        }
529
    }
530

    
531
    private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
532
            DescriptionElementBase element) {
533
        try {
534
            String[] csvLine;
535
            handleSource(state, element, CdmLightExportTable.MEDIA);
536

    
537
            if (element instanceof TextData) {
538
                TextData textData = (TextData) element;
539
                csvLine = new String[table.getSize()];
540
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
541
                if (cdmBase instanceof Taxon) {
542
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
543
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
544
                } else if (cdmBase instanceof TaxonName) {
545
                    csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
546
                    csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
547
                }
548

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

    
561
            }
562
        } catch (Exception e) {
563
            state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
564
                    + cdmBaseStr(element) + ": " + e.getMessage());
565
        }
566

    
567
    }
568

    
569
    private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
570
            DescriptionElementBase element) {
571
        try {
572
            String[] csvLine;
573
            handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
574

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

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

    
627
    private String filterIntextReferences(String text) {
628
        /*
629
         * (<cdm:reference cdmId='fbd19251-efee-4ded-b780-915000f66d41'
630
         * intextId='1352d42c-e201-4155-a02a-55360d3b563e'>Ridley in Fl. Malay
631
         * Pen. 3 (1924) 22</cdm:reference>)
632
         */
633
        String newText = text.replaceAll("<cdm:reference cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
634
        newText = newText.replaceAll("</cdm:reference>", "");
635

    
636
        newText = newText.replaceAll("<cdm:key cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
637
        newText = newText.replaceAll("</cdm:key>", "");
638
        return newText;
639
    }
640

    
641
    private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon,
642
            List<DescriptionElementBase> specimenFacts) {
643
        CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
644

    
645
        for (DescriptionElementBase element : specimenFacts) {
646
            try {
647
                String[] csvLine = new String[table.getSize()];
648
                csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
649
                csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
650
                handleSource(state, element, table);
651
                csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(
652
                        element.getAnnotations());
653

    
654
                if (element instanceof IndividualsAssociation) {
655

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

    
669
                            handleSpecimen(state, specimenBase);
670
                            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
671
                                    indAssociation.getAssociatedSpecimenOrObservation());
672
                        }
673
                    }
674
                } else if (element instanceof TextData) {
675
                    TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
676
                    csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(
677
                            textData.getMultilanguageText());
678
                }
679
                state.getProcessor().put(table, element, csvLine);
680
            } catch (Exception e) {
681
                state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact "
682
                        + cdmBaseStr(element) + ": " + e.getMessage());
683
            }
684
        }
685
    }
686

    
687
    private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
688
        String text = "";
689
        int index = multilanguageText.size();
690
        for (LanguageString langString : multilanguageText.values()) {
691
            text += langString.getText();
692
            if (index > 1) {
693
                text += "; ";
694
            }
695
            index--;
696
        }
697
        return text;
698
    }
699

    
700
    private String createAnnotationsString(Set<Annotation> annotations) {
701
        StringBuffer strBuff = new StringBuffer();
702

    
703
        for (Annotation ann : annotations) {
704
            if (ann.getAnnotationType() == null || !ann.getAnnotationType().equals(AnnotationType.TECHNICAL())) {
705
                strBuff.append(ann.getText());
706
                strBuff.append("; ");
707
            }
708
        }
709

    
710
        if (strBuff.length() > 2) {
711
            return strBuff.substring(0, strBuff.length() - 2);
712
        } else {
713
            return null;
714
        }
715
    }
716

    
717
    private void handleSource(CdmLightExportState state, DescriptionElementBase element,
718
            CdmLightExportTable factsTable) {
719
        CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
720
        try {
721
            Set<DescriptionElementSource> sources = element.getSources();
722

    
723
            for (DescriptionElementSource source : sources) {
724
                if (!(source.getType().equals(OriginalSourceType.Import)
725
                        && state.getConfig().isFilterImportSources())) {
726
                    String[] csvLine = new String[table.getSize()];
727
                    Reference ref = source.getCitation();
728
                    if ((ref == null) && (source.getNameUsedInSource() == null)) {
729
                        continue;
730
                    }
731
                    if (ref != null) {
732
                        if (!state.getReferenceStore().contains(ref.getUuid())) {
733
                            handleReference(state, ref);
734

    
735
                        }
736
                        csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
737
                    }
738
                    csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
739

    
740
                    csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state,
741
                            source.getNameUsedInSource());
742
                    csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
743
                    if (StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])
744
                            && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])) {
745
                        continue;
746
                    }
747
                    state.getProcessor().put(table, source, csvLine);
748
                }
749

    
750
            }
751
        } catch (Exception e) {
752
            state.getResult().addException(e, "An unexpected error occurred when handling single source "
753
                    + cdmBaseStr(element) + ": " + e.getMessage());
754
        }
755

    
756
    }
757

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

    
807
    }
808

    
809
    private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
810
            List<DescriptionElementBase> commonNameFacts) {
811
        CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
812

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

    
844
    /**
845
     * @param sec
846
     * @return
847
     */
848
    private String getTitleCache(IIdentifiableEntity identEntity) {
849
        if (identEntity == null) {
850
            return "";
851
        }
852
        // TODO refresh?
853
        return identEntity.getTitleCache();
854
    }
855

    
856
    private String getId(CdmLightExportState state, ICdmBase cdmBase) {
857
        if (cdmBase == null) {
858
            return "";
859
        }
860
        // TODO make configurable
861
        return cdmBase.getUuid().toString();
862
    }
863

    
864
    private void handleSynonym(CdmLightExportState state, Synonym synonym) {
865
        try {
866
            if (isUnpublished(state.getConfig(), synonym)) {
867
                return;
868
            }
869
            TaxonName name = synonym.getName();
870
            handleName(state, name);
871

    
872
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
873
            String[] csvLine = new String[table.getSize()];
874

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

    
894
    /**
895
     * Handles Misapplied names (including pro parte and partial as well as pro
896
     * parte and partial synonyms
897
     *
898
     * @param state
899
     * @param rel
900
     */
901
    private void handleProPartePartialMisapplied(CdmLightExportState state, TaxonRelationship rel) {
902
        try {
903
            Taxon ppSyonym = rel.getFromTaxon();
904
            if (isUnpublished(state.getConfig(), ppSyonym)) {
905
                return;
906
            }
907
            TaxonName name = ppSyonym.getName();
908
            handleName(state, name);
909

    
910
            CdmLightExportTable table = CdmLightExportTable.SYNONYM;
911
            String[] csvLine = new String[table.getSize()];
912

    
913
            csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, rel);
914
            csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, rel.getToTaxon());
915
            csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
916

    
917
            Reference secRef = ppSyonym.getSec();
918
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
919
            csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
920
            Reference synSecRef = rel.getCitation();
921
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
922
            csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
923

    
924
            // pro parte type
925
            TaxonRelationshipType type = rel.getType();
926
            csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = type.isProParte() ? "1" : "0";
927
            csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = type.isPartial() ? "1" : "0";
928
            csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = type.isAnyMisappliedName() ? "1" : "0";
929

    
930
            state.getProcessor().put(table, ppSyonym, csvLine);
931
        } catch (Exception e) {
932
            state.getResult().addException(e, "An unexpected error occurred when handling "
933
                    + "pro parte/partial synonym relationship " + cdmBaseStr(rel) + ": " + e.getMessage());
934
        }
935

    
936
    }
937

    
938
    private void handleName(CdmLightExportState state, TaxonName name){
939
        handleName(state, name, false);
940
    }
941

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

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

    
960
            handleIdentifier(state, name);
961
            handleDescriptions(state, name);
962

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

    
988

    
989
            if (!state.getConfig().isAddHTML()) {
990
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = name.getFullTitleCache();
991
            } else {
992
                List<TaggedText> taggedFullTitleCache = name.getTaggedFullTitle();
993
                String fullTitleWithHtml = createNameWithItalics(taggedFullTitleCache);
994
                // TODO: adapt the tropicos titlecache creation
995
                csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = fullTitleWithHtml.trim();
996
            }
997

    
998
            csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
999
            csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
1000

    
1001
            csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
1002
            csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
1003

    
1004
            csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
1005
            csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
1006
            if (name.getBasionymAuthorship() != null) {
1007
                if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
1008
                    handleAuthor(state, name.getBasionymAuthorship());
1009
                }
1010
            }
1011
            csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state,
1012
                    name.getExBasionymAuthorship());
1013
            if (name.getExBasionymAuthorship() != null) {
1014
                if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
1015
                    handleAuthor(state, name.getExBasionymAuthorship());
1016
                }
1017

    
1018
            }
1019
            csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,
1020
                    name.getCombinationAuthorship());
1021
            if (name.getCombinationAuthorship() != null) {
1022
                if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
1023
                    handleAuthor(state, name.getCombinationAuthorship());
1024
                }
1025
            }
1026
            csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state,
1027
                    name.getExCombinationAuthorship());
1028
            if (name.getExCombinationAuthorship() != null) {
1029
                if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
1030
                    handleAuthor(state, name.getExCombinationAuthorship());
1031
                }
1032

    
1033
            }
1034

    
1035
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
1036

    
1037
            Reference nomRef = name.getNomenclaturalReference();
1038

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

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

    
1124
                }
1125
            } else {
1126
                csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
1127
            }
1128

    
1129
            /*
1130
             * Collation
1131
             *
1132
             * Detail
1133
             *
1134
             * TitlePageYear
1135
             */
1136
            String protologueUriString = extractProtologueURIs(state, name);
1137

    
1138
            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
1139
            Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1140
            List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1141
            for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1142
                if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1143

    
1144
                    if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1145
                        Set<IdentifiableSource> sources =  typeDesignation.getSources();
1146
                        boolean isProtologue = false;
1147
                        if (sources != null && !sources.isEmpty()){
1148
                            IdentifiableSource source = sources.iterator().next();
1149
                            if (name.getNomenclaturalReference() != null){
1150
                                isProtologue = source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid());
1151
                            }
1152
                        }
1153
                        if (isProtologue){
1154
                            csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_TYPE_STATEMENT)] = ((TextualTypeDesignation) typeDesignation)
1155
                                    .getPreferredText(Language.DEFAULT());
1156
                        }else{
1157
                            textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1158
                        }
1159

    
1160
                    } else {
1161
                        textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1162
                    }
1163
                } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1164

    
1165
                    specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class));
1166

    
1167
                }
1168
            }
1169
            TypeDesignationSetManager manager = new TypeDesignationSetManager(specimenTypeDesignations, name);
1170
            String typeDesignationString = createTypeDesignationString(manager.toTaggedText(false, true, true), false, name.isSpecies() || name.isInfraSpecific());
1171
            csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = typeDesignationString;
1172

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

    
1200

    
1201
            if (name.getStatus() == null || name.getStatus().isEmpty()) {
1202
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
1203
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
1204
            } else {
1205

    
1206
                String statusStringAbbrev = extractStatusString(state, name, true);
1207
                String statusString = extractStatusString(state, name, false);
1208

    
1209
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
1210
                csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
1211
            }
1212

    
1213
            HomotypicalGroup group = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
1214

    
1215
            if (!state.containsHomotypicalGroupFromStore(group.getUuid())) {
1216
                if (acceptedName){
1217
                    handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
1218
                }else{
1219
                    handleHomotypicalGroup(state, HibernateProxyHelper.deproxy(group, HomotypicalGroup.class));
1220
                }
1221
            }
1222
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
1223
            List<TaxonName> typifiedNames = new ArrayList<>();
1224
            typifiedNames.addAll(group.getTypifiedNames());
1225
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1226
            Integer seqNumber = typifiedNames.indexOf(name);
1227
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1228
            state.getProcessor().put(table, name, csvLine);
1229
            handleNameRelationships(state, name);
1230

    
1231
        } catch (Exception e) {
1232
            state.getResult().addException(e,
1233
                    "An unexpected error occurred when handling synonym " + cdmBaseStr(name) + ": " + e.getMessage());
1234

    
1235
            e.printStackTrace();
1236
        }
1237
    }
1238

    
1239
    /**
1240
     * @param name
1241
     * @return
1242
     */
1243
    private String createNameWithItalics(List<TaggedText> taggedName) {
1244

    
1245
        String fullTitleWithHtml = "";
1246
        for (TaggedText taggedText: taggedName){
1247
            if (taggedText.getType().equals(TagEnum.name)){
1248
                fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1249
            }else if (taggedText.getType().equals(TagEnum.separator)){
1250
                fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1251
            }else{
1252
                fullTitleWithHtml += taggedText.getText() + " ";
1253
            }
1254
        }
1255
        return fullTitleWithHtml;
1256
    }
1257

    
1258
    private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1259
        Set<NameRelationship> rels = name.getRelationsFromThisName();
1260
        CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1261
        String[] csvLine = new String[table.getSize()];
1262

    
1263
        for (NameRelationship rel : rels) {
1264
            NameRelationshipType type = rel.getType();
1265
            TaxonName name2 = rel.getToName();
1266
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1267
            if (!state.getNameStore().containsKey(name2.getId())) {
1268
                handleName(state, name2);
1269
            }
1270

    
1271
            csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1272
            csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1273
            csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1274
            state.getProcessor().put(table, name, csvLine);
1275
        }
1276

    
1277
        rels = name.getRelationsToThisName();
1278

    
1279
        csvLine = new String[table.getSize()];
1280

    
1281
        for (NameRelationship rel : rels) {
1282
            NameRelationshipType type = rel.getType();
1283
            TaxonName name2 = rel.getFromName();
1284
            name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1285
            if (!state.getNameStore().containsKey(name2.getId())) {
1286
                handleName(state, name2);
1287
            }
1288

    
1289

    
1290
        }
1291
    }
1292

    
1293
    private String createCollatation(TaxonName name) {
1294
        String collation = "";
1295
        if (name.getNomenclaturalReference() != null) {
1296
            Reference ref = name.getNomenclaturalReference();
1297
            collation = getVolume(ref);
1298
        }
1299
        if (name.getNomenclaturalMicroReference() != null) {
1300
            if (!StringUtils.isBlank(collation)) {
1301
                collation += ":";
1302
            }
1303
            collation += name.getNomenclaturalMicroReference();
1304
        }
1305

    
1306
        return collation;
1307
    }
1308

    
1309
    private String getVolume(Reference reference) {
1310
        if (reference.getVolume() != null) {
1311
            return reference.getVolume();
1312
        } else if (reference.getInReference() != null) {
1313
            if (reference.getInReference().getVolume() != null) {
1314
                return reference.getInReference().getVolume();
1315
            }
1316
        }
1317
        return null;
1318
    }
1319

    
1320
    private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1321
        CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1322
        String[] csvLine;
1323
        try {
1324
            if (cdmBase instanceof TaxonName){
1325
                TaxonName name = (TaxonName)cdmBase;
1326

    
1327
                try{
1328
                    Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1329
                    Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1330
                    Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1331
                    if (!IPNIidentifiers.isEmpty()) {
1332
                        csvLine = new String[table.getSize()];
1333
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1334
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1335
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1336
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1337
                                IPNIidentifiers);
1338
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1339
                    }
1340
                    if (!tropicosIdentifiers.isEmpty()) {
1341
                        csvLine = new String[table.getSize()];
1342
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1343
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1344
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = name.getUuid() + ", " + IPNI_NAME_IDENTIFIER;
1345
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1346
                                tropicosIdentifiers);
1347
                        state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1348
                    }
1349
                    if (!WFOIdentifiers.isEmpty()) {
1350
                        csvLine = new String[table.getSize()];
1351
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1352
                        csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1353
                        csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1354
                        csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1355
                                WFOIdentifiers);
1356
                        state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1357
                    }
1358
                }catch(Exception e){
1359
                    state.getResult().addWarning("Please check the identifiers for "
1360
                            + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1361

    
1362

    
1363
                }
1364
            }else{
1365
                if (cdmBase instanceof IdentifiableEntity){
1366
                    IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1367
                    List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1368
                    String tableName = null;
1369
                    if (cdmBase instanceof Reference){
1370
                        tableName = "Reference";
1371
                    }else if (cdmBase instanceof SpecimenOrObservationBase){
1372
                        tableName = "Specimen";
1373
                    }else if (cdmBase instanceof Taxon){
1374
                        tableName = "Taxon";
1375
                    }else if (cdmBase instanceof Synonym){
1376
                        tableName = "Synonym";
1377
                    }else if (cdmBase instanceof TeamOrPersonBase){
1378
                        tableName = "PersonOrTeam";
1379
                    }
1380

    
1381
                    for (Identifier<?> identifier: identifiers){
1382
                        if (identifier.getType() == null && identifier.getIdentifier() == null){
1383
                            state.getResult().addWarning("Please check the identifiers for "
1384
                                    + cdmBaseStr(cdmBase) + " there is an empty identifier");
1385
                            continue;
1386
                        }
1387

    
1388
                        csvLine = new String[table.getSize()];
1389
                        csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1390

    
1391
                        if (tableName != null){
1392
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1393
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1394
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1395
                            state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1396
                        }
1397
                    }
1398
                    if (cdmBase instanceof Reference ){
1399
                        Reference ref = (Reference)cdmBase;
1400
                        if (ref.getDoi() != null){
1401
                            csvLine = new String[table.getSize()];
1402
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1403
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1404
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1405
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1406
                            state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1407
                        }
1408
                    }
1409

    
1410
                    if (cdmBase instanceof TeamOrPersonBase){
1411
                        TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1412
                        if (person instanceof Person &&  ((Person)person).getOrcid() != null){
1413
                            csvLine = new String[table.getSize()];
1414
                            csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1415
                            csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1416
                            csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1417
                            csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]=  ((Person)person).getOrcid().asURI();
1418
                            state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1419
                        }
1420
                    }
1421
                }
1422
            }
1423
        } catch (Exception e) {
1424
            state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1425
                    + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1426
            e.printStackTrace();
1427
        }
1428
    }
1429

    
1430
    private String extractIdentifier(Set<String> identifierSet) {
1431

    
1432
        String identifierString = "";
1433
        for (String identifier : identifierSet) {
1434
            if (!StringUtils.isBlank(identifierString)) {
1435
                identifierString += ", ";
1436
            }
1437
            identifierString += identifier;
1438
        }
1439
        return identifierString;
1440
    }
1441

    
1442
    private String extractProtologueURIs(CdmLightExportState state, TaxonName name) {
1443
        if (name.getNomenclaturalSource() != null){
1444
            Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1445
            return extractLinkUris(links.iterator());
1446
        }else{
1447
            return null;
1448
        }
1449
    }
1450

    
1451
    private String extractMediaURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1452
            Feature feature) {
1453

    
1454
        String mediaUriString = "";
1455
        Set<DescriptionElementBase> elements = new HashSet<>();
1456
        for (DescriptionBase<?> description : descriptionsSet) {
1457
            try {
1458
                if (!description.getElements().isEmpty()) {
1459
                    elements = description.getElements();
1460

    
1461
                    for (DescriptionElementBase element : elements) {
1462
                        Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1463
                        if (entityFeature.equals(feature)) {
1464
                            if (!element.getMedia().isEmpty()) {
1465
                                List<Media> media = element.getMedia();
1466
                                for (Media mediaElement : media) {
1467
                                    Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1468
                                    mediaUriString = extractMediaUris(it);
1469
                                }
1470
                            }
1471
                        }
1472
                    }
1473
                }
1474
            } catch (Exception e) {
1475
                state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1476
                        + cdmBaseStr(description) + ": " + e.getMessage());
1477
            }
1478
        }
1479
        return mediaUriString;
1480
    }
1481

    
1482
    private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1483
        try {
1484
            if (state.getAuthorFromStore(author.getId()) != null) {
1485
                return;
1486
            }
1487
            state.addAuthorToStore(author);
1488
            handleIdentifier(state, author);
1489
            CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1490
            String[] csvLine = new String[table.getSize()];
1491
            CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1492
            String[] csvLineRel = new String[tableAuthorRel.getSize()];
1493
            String[] csvLineMember = new String[table.getSize()];
1494
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1495
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1496
                    ? author.getTitleCache() : author.getNomenclaturalTitle();
1497
            csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1498
            author = HibernateProxyHelper.deproxy(author);
1499
            if (author instanceof Person) {
1500
                Person authorPerson = (Person) author;
1501
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1502
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1503
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1504
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1505
            } else {
1506
                // create an entry in rel table and all members in author table,
1507
                // check whether the team members already in author table
1508

    
1509
                Team authorTeam = (Team) author;
1510
                int index = 0;
1511
                for (Person member : authorTeam.getTeamMembers()) {
1512
                    csvLineRel = new String[tableAuthorRel.getSize()];
1513
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1514
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1515
                    csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1516
                            .valueOf(index);
1517
                    state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1518

    
1519
                    if (state.getAuthorFromStore(member.getId()) == null) {
1520
                        state.addAuthorToStore(member);
1521
                        csvLineMember = new String[table.getSize()];
1522
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1523
                        csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1524
                                .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitle();
1525
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1526
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1527
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1528
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1529
                        csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1530
                        state.getProcessor().put(table, member, csvLineMember);
1531
                    }
1532
                    index++;
1533
                }
1534
            }
1535
            state.getProcessor().put(table, author, csvLine);
1536
        } catch (Exception e) {
1537
            state.getResult().addException(e,
1538
                    "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1539
        }
1540
    }
1541

    
1542
    private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1543
        try {
1544
            Set<NomenclaturalStatus> status = name.getStatus();
1545
            if (status.isEmpty()) {
1546
                return "";
1547
            }
1548
            String statusString = "";
1549
            for (NomenclaturalStatus nameStatus : status) {
1550
                if (nameStatus != null) {
1551
                    if (abbrev) {
1552
                        if (nameStatus.getType() != null) {
1553
                            statusString += nameStatus.getType().getIdInVocabulary();
1554
                        }
1555
                    } else {
1556
                        if (nameStatus.getType() != null) {
1557
                            statusString += nameStatus.getType().getTitleCache();
1558
                        }
1559
                    }
1560
                    if (!abbrev) {
1561

    
1562
                        if (nameStatus.getRuleConsidered() != null
1563
                                && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1564
                            statusString += " " + nameStatus.getRuleConsidered();
1565
                        }
1566
                        if (nameStatus.getCitation() != null) {
1567
                            statusString += " " + nameStatus.getCitation().getTitleCache();
1568
                        }
1569
                        if (nameStatus.getCitationMicroReference() != null
1570
                                && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1571
                            statusString += " " + nameStatus.getCitationMicroReference();
1572
                        }
1573
                    }
1574
                    statusString += " ";
1575
                }
1576
            }
1577
            return statusString;
1578
        } catch (Exception e) {
1579
            state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1580
                    + cdmBaseStr(name) + ": " + e.getMessage());
1581
            return "";
1582
        }
1583
    }
1584

    
1585
    private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group) {
1586
        try {
1587
            state.addHomotypicalGroupToStore(group);
1588
            CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1589
            String[] csvLine = new String[table.getSize()];
1590

    
1591
            csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1592
            List<TaxonName> typifiedNames = new ArrayList<>();
1593
//            typifiedNames.addAll(group.getTypifiedNames());
1594
            group.getTypifiedNames().stream().forEach(name -> typifiedNames.add(HibernateProxyHelper.deproxy(name, TaxonName.class)));
1595
            TaxonName firstname = null;
1596
            for (TaxonName name: typifiedNames){
1597
                Iterator<Taxon> taxa = name.getTaxa().iterator();
1598
                while(taxa.hasNext()){
1599
                    Taxon taxon = taxa.next();
1600
                    if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1601
                        firstname = name;
1602
                        break;
1603
                    }
1604
                }
1605
            }
1606

    
1607
            Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1608
            String typifiedNamesString = "";
1609
            String typifiedNamesWithSecString = "";
1610
            String typifiedNamesWithoutAccepted = "";
1611
            String typifiedNamesWithoutAcceptedWithSec = "";
1612
            int index = 0;
1613
            for (TaxonName name : typifiedNames) {
1614
                // Concatenated output string for homotypic group (names and
1615
                // citations) + status + some name relations (e.g. “non”)
1616
                // TODO: nameRelations, which and how to display
1617
                Set<TaxonBase> taxonBases = name.getTaxonBases();
1618
                TaxonBase taxonBase;
1619

    
1620
                String sec = "";
1621
                String nameString = name.getFullTitleCache();
1622

    
1623
                if (state.getConfig().isAddHTML()){
1624
                    nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1625
                }
1626

    
1627
                if (index > 0){
1628
                    boolean isInvalid = false;
1629
                    for (NomenclaturalStatus status: name.getStatus()){
1630
                        if (status != null && status.getType() != null && status.getType().isInvalidType()){
1631
                            isInvalid = true;
1632
                            break;
1633
                        }
1634
                    }
1635
                    if (isInvalid){
1636
                        nameString = "\u2212 " + nameString;
1637
                    }else{
1638
                        nameString = "\u2261 " + nameString;
1639
                    }
1640
                }
1641
                boolean isAccepted = false;
1642

    
1643
                if (taxonBases.size() == 1){
1644
                     taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
1645
                     Reference secRef = taxonBase.getSec();
1646
                     if (secRef != null){
1647
                         sec = ((DefaultReferenceCacheStrategy) secRef.getCacheStrategy())
1648
                             .createShortCitation(secRef);
1649
                     }
1650
                     if (taxonBase instanceof Synonym){
1651
                         if (StringUtils.isNotBlank(sec)){
1652
                             sec = " syn. sec. " + sec;
1653
                         }else {
1654
                             sec = "";
1655
                         }
1656
                         typifiedNamesWithoutAccepted += nameString ;
1657
                         typifiedNamesWithoutAcceptedWithSec += nameString + sec ;
1658
                     }else{
1659
                         sec = "";
1660
                         if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
1661
                             isAccepted = true;
1662
                         }
1663

    
1664
                     }
1665

    
1666
                }else{
1667
                    //there are names used more than once?
1668
                    for (TaxonBase tb: taxonBases){
1669
                        Reference secRef = tb.getSec();
1670
                        if (secRef != null){
1671
                            sec = ((DefaultReferenceCacheStrategy) secRef.getCacheStrategy())
1672
                                .createShortCitation(secRef);
1673
                        }
1674
                        if (tb instanceof Synonym){
1675
                            if (StringUtils.isNotBlank(sec)){
1676
                                sec = " syn. sec. " + sec;
1677
                            }else {
1678
                                sec = "";
1679
                            }
1680
                            break;
1681
                        }else{
1682
                            sec = "";
1683
                            if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
1684
                                isAccepted = true;
1685
                                break;
1686
                            }
1687

    
1688
                        }
1689
                    }
1690
                    if (!isAccepted){
1691
                        typifiedNamesWithoutAccepted += nameString + "; ";
1692
                        typifiedNamesWithoutAcceptedWithSec += nameString + sec + "; ";
1693
                    }
1694
                }
1695
                typifiedNamesString += nameString ;
1696
                typifiedNamesWithSecString += nameString + sec;
1697

    
1698

    
1699
                if (typifiedNamesString != null) {
1700
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
1701
                } else {
1702
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
1703
                }
1704

    
1705

    
1706
                if (typifiedNamesWithSecString != null) {
1707
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
1708
                } else {
1709
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = "";
1710
                }
1711

    
1712
                if (typifiedNamesWithoutAccepted != null && firstname != null) {
1713
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
1714
                } else {
1715
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = "";
1716
                }
1717

    
1718
                if (typifiedNamesWithoutAcceptedWithSec != null && firstname != null) {
1719
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = typifiedNamesWithoutAcceptedWithSec.trim();
1720
                } else {
1721
                    csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = "";
1722
                }
1723
                index++;
1724
            }
1725

    
1726
            Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
1727
            List<TypeDesignationBase<?>> designationList = new ArrayList<>();
1728
            designationList.addAll(typeDesigantionSet);
1729
            Collections.sort(designationList, new TypeComparator());
1730

    
1731
            List<TaggedText> list = new ArrayList<>();
1732
            if (!designationList.isEmpty()) {
1733
                TypeDesignationSetManager manager = new TypeDesignationSetManager(group);
1734
                list.addAll(manager.toTaggedText(true, false, false));
1735
            }
1736
            String typeTextDesignations = "";
1737
            //The typeDesignationManager does not handle the textual typeDesignations
1738
            for (TypeDesignationBase<?> typeDes: designationList) {
1739
            	if (typeDes instanceof TextualTypeDesignation) {
1740
            		typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
1741
            		typeTextDesignations =  typeTextDesignations + "; ";
1742
            	}
1743
            }
1744
            if (typeTextDesignations.equals("; ")) {
1745
            	typeTextDesignations = "";
1746
            }
1747
            if (StringUtils.isNotBlank(typeTextDesignations)) {
1748
            	typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
1749
            }
1750
            String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
1751

    
1752
            // typeDesignations = typeDesignationString.toString();
1753
            if (StringUtils.isNotBlank(specimenTypeString)) {
1754
                if (!specimenTypeString.endsWith(".")) {
1755
                	specimenTypeString = specimenTypeString + ".";
1756
                }
1757
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
1758

    
1759
            } else {
1760
                csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
1761
            }
1762
            if (StringUtils.isNotBlank(typeTextDesignations)) {
1763
                if (!typeTextDesignations.endsWith(".")) {
1764
                	typeTextDesignations = typeTextDesignations + ".";
1765
                }
1766
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
1767

    
1768
            } else {
1769
                csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
1770
            }
1771
            state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
1772
        } catch (Exception e) {
1773
            e.printStackTrace();
1774
            state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
1775
                    + cdmBaseStr(group) + ": " + e.getMessage());
1776
        }
1777
    }
1778

    
1779
    private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup, boolean isSpecimenTypeDesignation) {
1780
        StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
1781

    
1782
        for (TaggedText text : list) {
1783
            if (text != null && text.getText() != null
1784
                    && (text.getText().equals("Type:") || text.getText().equals("NameType:") || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
1785
                // do nothing
1786
            } else if (text.getType().equals(TagEnum.reference)) {
1787
                homotypicalGroupTypeDesignationString.append(text.getText());
1788
            } else if (text.getType().equals(TagEnum.typeDesignation) ) {
1789
                if(isSpecimenTypeDesignation){
1790
                    homotypicalGroupTypeDesignationString
1791
                    .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
1792
                }else{
1793
                    homotypicalGroupTypeDesignationString
1794
                    .append(text.getText());
1795
                }
1796

    
1797
            } else {
1798
                homotypicalGroupTypeDesignationString.append(text.getText());
1799
            }
1800
        }
1801

    
1802
        String typeDesignations = homotypicalGroupTypeDesignationString.toString();
1803
        typeDesignations = typeDesignations.trim();
1804

    
1805
        if (typeDesignations.endsWith(";")){
1806
            typeDesignations = typeDesignations.substring(0, typeDesignations.length()-1);
1807
        }
1808
        typeDesignations += ".";
1809
        typeDesignations = typeDesignations.replace("..", ".");
1810
        typeDesignations = typeDesignations.replace(". .", ".");
1811

    
1812
        if (typeDesignations.trim().equals(".")) {
1813
            typeDesignations = null;
1814
        }
1815
        return typeDesignations;
1816
    }
1817

    
1818
    private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
1819
        try {
1820
            String basionymStart = "(";
1821
            String basionymEnd = ") ";
1822
            String exAuthorSeperator = " ex ";
1823
            TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
1824
            TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
1825
            TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
1826
            TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
1827

    
1828
            String combinationAuthorString = "";
1829
            if (combinationAuthor != null) {
1830
                combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
1831
                if (combinationAuthor instanceof Team) {
1832
                    combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
1833
                } else {
1834
                    Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
1835
                    combinationAuthorString = createTropicosAuthorString(person);
1836
                }
1837
            }
1838
            String exCombinationAuthorString = "";
1839
            if (exCombinationAuthor != null) {
1840
                exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
1841
                if (exCombinationAuthor instanceof Team) {
1842
                    exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
1843
                } else {
1844
                    Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
1845
                    exCombinationAuthorString = createTropicosAuthorString(person);
1846
                }
1847
            }
1848

    
1849
            String basionymAuthorString = "";
1850
            if (basionymAuthor != null) {
1851
                basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
1852
                if (basionymAuthor instanceof Team) {
1853
                    basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
1854
                } else {
1855
                    Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
1856
                    basionymAuthorString = createTropicosAuthorString(person);
1857
                }
1858
            }
1859

    
1860
            String exBasionymAuthorString = "";
1861

    
1862
            if (exBasionymAuthor != null) {
1863
                exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
1864
                if (exBasionymAuthor instanceof Team) {
1865
                    exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
1866

    
1867
                } else {
1868
                    Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
1869
                    exBasionymAuthorString = createTropicosAuthorString(person);
1870
                }
1871
            }
1872
            String completeAuthorString = name.getNameCache() + " ";
1873

    
1874
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
1875
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
1876
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
1877
                    ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
1878
            completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
1879
            completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
1880
                    || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
1881
            completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
1882
                    ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
1883
            completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
1884
                    : "";
1885

    
1886
            return completeAuthorString;
1887
        } catch (Exception e) {
1888
            state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
1889
                    + cdmBaseStr(name) + ": " + e.getMessage());
1890
            return null;
1891
        }
1892
    }
1893

    
1894
    private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
1895
        String combinationAuthorString;
1896
        Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
1897
        Team tempTeam = Team.NewInstance();
1898
        for (Person teamMember : team.getTeamMembers()) {
1899
            combinationAuthorString = createTropicosAuthorString(teamMember);
1900
            Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
1901
            tempTeam.addTeamMember(tempPerson);
1902
        }
1903
        combinationAuthorString = tempTeam.generateTitle();
1904
        return combinationAuthorString;
1905
    }
1906

    
1907
    private String createTropicosAuthorString(Person teamMember) {
1908
        String nomAuthorString = "";
1909
        String[] splittedAuthorString = null;
1910
        if (teamMember == null) {
1911
            return nomAuthorString;
1912
        }
1913

    
1914
        if (teamMember.getGivenName() != null) {
1915
            String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
1916
            splittedAuthorString = givenNameString.split("\\s");
1917
            for (String split : splittedAuthorString) {
1918
                if (!StringUtils.isBlank(split)) {
1919
                    nomAuthorString += split.substring(0, 1);
1920
                    nomAuthorString += ".";
1921
                }
1922
            }
1923
        }
1924
        if (teamMember.getFamilyName() != null) {
1925
            String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
1926
            splittedAuthorString = familyNameString.split("\\s");
1927
            for (String split : splittedAuthorString) {
1928
                nomAuthorString += " " + split;
1929
            }
1930
        }
1931
        if (isBlank(nomAuthorString.trim())) {
1932
            if (teamMember.getTitleCache() != null) {
1933
                String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
1934
                splittedAuthorString = titleCacheString.split("\\s");
1935
            } else {
1936
                splittedAuthorString = new String[0];
1937
            }
1938

    
1939
            int index = 0;
1940
            for (String split : splittedAuthorString) {
1941
                if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
1942
                    nomAuthorString += split;
1943
                } else {
1944
                    nomAuthorString = nomAuthorString + " " + split;
1945
                }
1946
                index++;
1947
            }
1948
        }
1949
        return nomAuthorString.trim();
1950
    }
1951

    
1952
    private void handleReference(CdmLightExportState state, Reference reference) {
1953
        try {
1954
            state.addReferenceToStore(reference);
1955
            CdmLightExportTable table = CdmLightExportTable.REFERENCE;
1956
            reference = HibernateProxyHelper.deproxy(reference, Reference.class);
1957

    
1958
            handleIdentifier(state, reference);
1959
            String[] csvLine = new String[table.getSize()];
1960
            csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
1961
            // TODO short citations correctly
1962
            String shortCitation = ((DefaultReferenceCacheStrategy) reference.getCacheStrategy())
1963
                    .createShortCitation(reference); // Should be Author(year)
1964
                                                     // like in Taxon.sec
1965
            csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
1966
            // TODO get preferred title
1967
            csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
1968
                    ? reference.getTitleCache() : reference.getTitle();
1969
            csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
1970
                    ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
1971
            csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
1972
            // TBC
1973
            csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
1974
            csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
1975
            csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
1976
            csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
1977
            csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
1978
            csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
1979
            csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
1980
            csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
1981
            csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
1982
            csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
1983
            csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
1984
            csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
1985

    
1986
            if (reference.getAuthorship() != null) {
1987
                csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
1988
                csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
1989
            }
1990

    
1991
            csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
1992
            if (reference.getInReference() != null
1993
                    && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
1994
                handleReference(state, reference.getInReference());
1995
            }
1996
            if (reference.getInstitution() != null) {
1997
                csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
1998
            }
1999
            if (reference.getLsid() != null) {
2000
                csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
2001
            }
2002
            if (reference.getSchool() != null) {
2003
                csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
2004
            }
2005
            if (reference.getUri() != null) {
2006
                csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
2007
            }
2008
            csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
2009

    
2010
            state.getProcessor().put(table, reference, csvLine);
2011
        } catch (Exception e) {
2012
            state.getResult().addException(e, "An unexpected error occurred when handling reference "
2013
                    + cdmBaseStr(reference) + ": " + e.getMessage());
2014
        }
2015
    }
2016

    
2017
    private String createFullAuthorship(Reference reference) {
2018
        TeamOrPersonBase<?> authorship = reference.getAuthorship();
2019
        String fullAuthorship = "";
2020
        if (authorship == null) {
2021
            return null;
2022
        }
2023
        authorship = HibernateProxyHelper.deproxy(authorship);
2024
        if (authorship instanceof Person) {
2025
            fullAuthorship = ((Person) authorship).getTitleCache();
2026

    
2027
        } else if (authorship instanceof Team) {
2028

    
2029
            Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
2030
            int index = 0;
2031

    
2032
            for (Person teamMember : authorTeam.getTeamMembers()) {
2033
                index++;
2034
                String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
2035
                fullAuthorship += concat + teamMember.getTitleCache();
2036
            }
2037
            if (StringUtils.isBlank(fullAuthorship)){
2038
                fullAuthorship = authorTeam.getTitleCache();
2039
            }
2040
        }
2041
        return fullAuthorship;
2042
    }
2043

    
2044
    private static String concatString(Team team, List<Person> teamMembers, int i) {
2045
        String concat;
2046
        if (i <= 1) {
2047
            concat = "";
2048
        } else if (i < teamMembers.size() || (team.isHasMoreMembers() && i == teamMembers.size())) {
2049
            concat = STD_TEAM_CONCATINATION;
2050
        } else {
2051
            concat = FINAL_TEAM_CONCATINATION;
2052
        }
2053
        return concat;
2054
    }
2055

    
2056
    /*
2057
     * TypeDesignation table Specimen_Fk EditName_Fk TypeVerbatimCitation
2058
     * TypeCategory TypeDesignatedByString TypeDesignatedByRef_Fk
2059
     */
2060

    
2061
    // private void handleSpecimenTypeDesignations(CdmLightExportState state,
2062
    // TaxonName name){
2063
    // try {
2064
    // Set<SpecimenTypeDesignation> typeDesignations =
2065
    // name.getSpecimenTypeDesignations();
2066
    // CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
2067
    // String nameId = getId(state, name);
2068
    // String[] csvLine = new String[table.getSize()];
2069
    // for (SpecimenTypeDesignation specimenType: typeDesignations){
2070
    // csvLine = new String[table.getSize()];
2071
    // DerivedUnit specimen = specimenType.getTypeSpecimen();
2072
    // if (state.getSpecimenFromStore(specimen.getId()) == null){
2073
    // handleSpecimen(state, specimen);
2074
    // }
2075
    // csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
2076
    // specimenType.getTypeSpecimen());
2077
    // csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
2078
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] =
2079
    // specimenType.getTypeSpecimen().generateTitle();
2080
    // //TODO: add link to existing Vorcabulary
2081
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
2082
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] =
2083
    // specimenType.getCitation().getTitleCache();
2084
    // csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] =
2085
    // getId(state, specimenType.getCitation());
2086
    // }
2087
    // } catch (Exception e) {
2088
    // state.getResult().addException(e, "An unexpected error occurred when
2089
    // handling specimen type designations for " +
2090
    // cdmBaseStr(name) + ": " + e.getMessage());
2091
    // }
2092
    // }
2093

    
2094
    private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
2095
        try {
2096
            state.addSpecimenToStore(specimen);
2097
            CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
2098
            String specimenId = getId(state, specimen);
2099
            String[] csvLine = new String[table.getSize()];
2100

    
2101
            /*
2102
             * SpecimenCitation = “El Salvador, Municipio La Libertad, San
2103
             * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
2104
             * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
2105
             * HerbariumCode
2106
             *
2107
             */
2108

    
2109
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
2110
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
2111
            Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
2112
            if (fieldUnits.size() == 1) {
2113
                Iterator<FieldUnit> iterator = fieldUnits.iterator();
2114
                if (iterator.hasNext()){
2115
                    FieldUnit fieldUnit = iterator.next();
2116
                    csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
2117
                }
2118
            }
2119
            if (specimen.isInstanceOf(DerivedUnit.class)){
2120
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
2121
                if (!StringUtils.isBlank(derivedUnit.getBarcode())){
2122
                    csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
2123
                }
2124
                if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
2125
                    csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
2126
                }
2127
                if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
2128
                    csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
2129
                }
2130
            }
2131

    
2132
            csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
2133
            csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
2134
                    specimen.getDescriptions(), Feature.IMAGE());
2135
            if (specimen instanceof DerivedUnit) {
2136
                DerivedUnit derivedUnit = (DerivedUnit) specimen;
2137
                if (derivedUnit.getCollection() != null) {
2138
                    csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
2139
                            .getCode();
2140
                }
2141

    
2142
                if (specimen instanceof MediaSpecimen) {
2143
                    MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
2144
                    Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
2145
                    String mediaUris = extractMediaUris(it);
2146
                    csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
2147

    
2148
                }
2149

    
2150
                if (derivedUnit.getDerivedFrom() != null) {
2151
                    for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
2152
                        // TODO: What to do if there are more then one
2153
                        // FieldUnit??
2154
                        if (original instanceof FieldUnit) {
2155
                            FieldUnit fieldUnit = (FieldUnit) original;
2156
                            csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
2157

    
2158
                            GatheringEvent gathering = fieldUnit.getGatheringEvent();
2159
                            if (gathering != null) {
2160
                                if (gathering.getLocality() != null) {
2161
                                    csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
2162
                                            .getText();
2163
                                }
2164
                                if (gathering.getCountry() != null) {
2165
                                    csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
2166
                                            .getLabel();
2167
                                }
2168
                                csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2169
                                        state, gathering, fieldUnit);
2170

    
2171
                                if (gathering.getGatheringDate() != null) {
2172
                                    csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2173
                                            .getGatheringDate().toString();
2174
                                }
2175
                                if (!gathering.getCollectingAreas().isEmpty()) {
2176
                                    int index = 0;
2177
                                    csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2178
                                    for (NamedArea area : gathering.getCollectingAreas()) {
2179
                                        if (index == 0) {
2180
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2181
                                                    .getLevel().getLabel():"";
2182
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2183
                                        }
2184
                                        if (index == 1) {
2185
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2186
                                                    .getLevel().getLabel():"";
2187
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2188
                                        }
2189
                                        if (index == 2) {
2190
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2191
                                                    .getLevel().getLabel():"";
2192
                                            csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2193
                                        }
2194
                                        if (index == 3) {
2195
                                            csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2196
                                            break;
2197
                                        }
2198
                                        index++;
2199
                                    }
2200
                                }
2201
                            }
2202
                        }
2203
                    }
2204
                } else {
2205
                    state.getResult().addError("The specimen with uuid " + specimen.getUuid()
2206
                            + " is not an DerivedUnit. Could not be exported.");
2207
                }
2208
            }
2209

    
2210
            state.getProcessor().put(table, specimen, csvLine);
2211
        } catch (Exception e) {
2212
            state.getResult().addException(e, "An unexpected error occurred when handling specimen "
2213
                    + cdmBaseStr(specimen) + ": " + e.getMessage());
2214
        }
2215
    }
2216

    
2217
    private String extractMediaUris(Iterator<MediaRepresentation> it) {
2218

    
2219
        String mediaUriString = "";
2220
        boolean first = true;
2221
        while (it.hasNext()) {
2222
            MediaRepresentation rep = it.next();
2223
            List<MediaRepresentationPart> parts = rep.getParts();
2224
            for (MediaRepresentationPart part : parts) {
2225
                if (first) {
2226
                    if (part.getUri() != null) {
2227
                        mediaUriString += part.getUri().toString();
2228
                        first = false;
2229
                    }
2230
                } else {
2231
                    if (part.getUri() != null) {
2232
                        mediaUriString += ", " + part.getUri().toString();
2233
                    }
2234
                }
2235
            }
2236
        }
2237

    
2238
        return mediaUriString;
2239
    }
2240

    
2241
    private String extractLinkUris(Iterator<ExternalLink> it) {
2242

    
2243
        String linkUriString = "";
2244
        boolean first = true;
2245
        while (it.hasNext()) {
2246
            ExternalLink link = it.next();
2247
            if (first) {
2248
                if (link.getUri() != null) {
2249
                    linkUriString += link.getUri().toString();
2250
                    first = false;
2251
                }
2252
            } else {
2253
                if (link.getUri() != null) {
2254
                    linkUriString += ", " + link.getUri().toString();
2255
                }
2256
            }
2257
        }
2258
        return linkUriString;
2259
    }
2260

    
2261
    private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2262
        try {
2263
            String collectorString = "";
2264
            AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2265
            if (gathering.getCollector() != null) {
2266
                if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2267

    
2268
                    Person primaryCollector = fieldUnit.getPrimaryCollector();
2269
                    if (collectorA instanceof Team) {
2270
                        Team collectorTeam = (Team) collectorA;
2271
                        boolean isFirst = true;
2272
                        for (Person member : collectorTeam.getTeamMembers()) {
2273
                            if (!isFirst) {
2274
                                collectorString += "; ";
2275
                            }
2276
                            if (member.equals(primaryCollector)) {
2277
                                // highlight
2278
                                collectorString += "<b>" + member.getTitleCache() + "</b>";
2279
                            } else {
2280
                                collectorString += member.getTitleCache();
2281
                            }
2282
                        }
2283
                    }
2284
                } else {
2285
                    collectorString = collectorA.getTitleCache();
2286
                }
2287
            }
2288
            return collectorString;
2289
        } catch (Exception e) {
2290
            state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2291
                    + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2292
            return "";
2293
        }
2294
    }
2295

    
2296
    /**
2297
     * Returns a string representation of the {@link CdmBase cdmBase} object for
2298
     * result messages.
2299
     */
2300
    private String cdmBaseStr(CdmBase cdmBase) {
2301
        if (cdmBase == null) {
2302
            return "-no object available-";
2303
        } else {
2304
            return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2305
        }
2306
    }
2307

    
2308
    @Override
2309
    protected boolean doCheck(CdmLightExportState state) {
2310
        return false;
2311
    }
2312

    
2313
    @Override
2314
    protected boolean isIgnore(CdmLightExportState state) {
2315
        return false;
2316
    }
2317

    
2318
}
(1-1/6)