2 * Copyright (C) 2017 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.cdm
.io
.wfo
.out
;
12 import java
.util
.ArrayList
;
13 import java
.util
.HashSet
;
14 import java
.util
.Iterator
;
15 import java
.util
.List
;
19 import org
.apache
.commons
.lang3
.StringUtils
;
20 import org
.joda
.time
.DateTime
;
21 import org
.joda
.time
.DateTimeFieldType
;
22 import org
.joda
.time
.Partial
;
23 import org
.joda
.time
.format
.DateTimeFormatter
;
24 import org
.joda
.time
.format
.DateTimeFormatterBuilder
;
25 import org
.springframework
.stereotype
.Component
;
27 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
28 import eu
.etaxonomy
.cdm
.common
.URI
;
29 import eu
.etaxonomy
.cdm
.common
.monitor
.IProgressMonitor
;
30 import eu
.etaxonomy
.cdm
.filter
.TaxonNodeFilter
;
31 import eu
.etaxonomy
.cdm
.format
.reference
.NomenclaturalSourceFormatter
;
32 import eu
.etaxonomy
.cdm
.io
.common
.CdmExportBase
;
33 import eu
.etaxonomy
.cdm
.io
.common
.ExportResult
.ExportResultState
;
34 import eu
.etaxonomy
.cdm
.io
.common
.TaxonNodeOutStreamPartitioner
;
35 import eu
.etaxonomy
.cdm
.io
.common
.XmlExportState
;
36 import eu
.etaxonomy
.cdm
.io
.common
.mapping
.out
.IExportTransformer
;
37 import eu
.etaxonomy
.cdm
.model
.common
.AnnotatableEntity
;
38 import eu
.etaxonomy
.cdm
.model
.common
.Annotation
;
39 import eu
.etaxonomy
.cdm
.model
.common
.AnnotationType
;
40 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
41 import eu
.etaxonomy
.cdm
.model
.common
.ICdmBase
;
42 import eu
.etaxonomy
.cdm
.model
.common
.IIdentifiableEntity
;
43 import eu
.etaxonomy
.cdm
.model
.common
.Identifier
;
44 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
45 import eu
.etaxonomy
.cdm
.model
.common
.LanguageString
;
46 import eu
.etaxonomy
.cdm
.model
.common
.TimePeriod
;
47 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
48 import eu
.etaxonomy
.cdm
.model
.name
.HomotypicalGroup
;
49 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
50 import eu
.etaxonomy
.cdm
.model
.name
.TaxonName
;
51 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
52 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
53 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
54 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
55 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
56 import eu
.etaxonomy
.cdm
.model
.term
.IdentifierType
;
59 * Classification or taxon tree exporter into WFO DwC-A format.
65 public class WfoClassificationExport
66 extends CdmExportBase
<WfoExportConfigurator
,WfoExportState
,IExportTransformer
,File
>{
68 private static final long serialVersionUID
= -4560488499411723333L;
70 public WfoClassificationExport() {
71 this.ioName
= this.getClass().getSimpleName();
75 public long countSteps(WfoExportState state
) {
76 TaxonNodeFilter filter
= state
.getConfig().getTaxonNodeFilter();
77 return getTaxonNodeService().count(filter
);
81 protected void doInvoke(WfoExportState state
) {
84 IProgressMonitor monitor
= state
.getConfig().getProgressMonitor();
85 WfoExportConfigurator config
= state
.getConfig();
88 if (config
.getTaxonNodeFilter().hasClassificationFilter()) {
89 Classification classification
= getClassificationService()
90 .load(config
.getTaxonNodeFilter().getClassificationFilter().get(0).getUuid());
91 state
.setRootId(classification
.getRootNode().getUuid());
92 } else if (config
.getTaxonNodeFilter().hasSubtreeFilter()) {
93 state
.setRootId(config
.getTaxonNodeFilter().getSubtreeFilter().get(0).getUuid());
96 @SuppressWarnings({ "unchecked", "rawtypes" })
97 TaxonNodeOutStreamPartitioner
<XmlExportState
> partitioner
= TaxonNodeOutStreamPartitioner
.NewInstance(this,
98 state
, state
.getConfig().getTaxonNodeFilter(), 100, monitor
, null);
100 // handleMetaData(state); //FIXME metadata;
101 monitor
.subTask("Start partitioning");
103 TaxonNode node
= partitioner
.next();
104 while (node
!= null) {
105 handleTaxonNode(state
, node
);
106 node
= partitioner
.next();
109 state
.getProcessor().createFinalResult(state
);
110 } catch (Exception e
) {
111 state
.getResult().addException(e
,
112 "An unexpected error occurred in main method doInvoke() " + e
.getMessage());
117 private void handleTaxonNode(WfoExportState state
, TaxonNode taxonNode
) {
119 if (taxonNode
== null) {
120 // TODO 5 taxon node not found
121 String message
= "TaxonNode for given taxon node UUID not found.";
122 state
.getResult().addError(message
);
125 boolean exclude
= filterTaxon(state
, taxonNode
);
128 String parentWfoId
= getParentWfoId(state
, taxonNode
);
129 if (taxonNode
.hasTaxon()) {
131 state
.putTaxonNodeWfoId(taxonNode
, parentWfoId
); //always use parent instead
133 String wfoId
= handleTaxon(state
, taxonNode
, parentWfoId
);
134 state
.putTaxonNodeWfoId(taxonNode
, wfoId
);
136 state
.putTaxonNodeWfoId(taxonNode
, parentWfoId
);
138 } catch (Exception e
) {
139 state
.getResult().addException(e
, "An unexpected error occurred when handling taxonNode "
140 + taxonNode
.getUuid() + ": " + e
.getMessage() + e
.getStackTrace());
145 private String
getParentWfoId(WfoExportState state
, TaxonNode taxonNode
) {
146 TaxonNode parentNode
= taxonNode
.getParent();
147 if (parentNode
== null) {
150 String wfoId
= state
.getTaxonNodeWfoId(parentNode
);
154 wfoId
= parentNode
.getTaxon() == null ?
null
155 : getWfoId(state
, parentNode
.getTaxon().getName(), true);
157 state
.putTaxonNodeWfoId(parentNode
, wfoId
);
158 state
.putTaxonWfoId(parentNode
.getTaxon(), wfoId
);
159 state
.putNameWfoId(parentNode
.getTaxon().getName(), wfoId
);
166 private Set
<Rank
> allowedRanks
= new HashSet
<>();
167 private boolean filterTaxon(WfoExportState state
, TaxonNode taxonNode
) {
168 Taxon taxon
= taxonNode
.getTaxon();
172 TaxonName taxonName
= taxon
.getName();
173 if (taxonName
== null) {
175 }else if (taxonName
.isHybridFormula()) {
178 String wfoId
= getWfoId(state
, taxonName
, false);
184 Rank rank
= taxonName
.getRank();
188 if (allowedRanks
.isEmpty()) {
189 allowedRanks
.add(Rank
.FAMILY());
190 allowedRanks
.add(Rank
.SUBFAMILY());
191 allowedRanks
.add(Rank
.TRIBE());
192 allowedRanks
.add(Rank
.SUBTRIBE());
193 allowedRanks
.add(Rank
.GENUS());
194 allowedRanks
.add(Rank
.SUBGENUS());
195 allowedRanks
.add(Rank
.SECTION_BOTANY());
196 allowedRanks
.add(Rank
.SPECIES());
197 allowedRanks
.add(Rank
.SUBSPECIES());
198 allowedRanks
.add(Rank
.VARIETY());
199 allowedRanks
.add(Rank
.SUBVARIETY());
200 allowedRanks
.add(Rank
.FORM());
201 allowedRanks
.add(Rank
.SUBFORM());
202 allowedRanks
.add(Rank
.INFRASPECIFICTAXON());
204 if (!allowedRanks
.contains(rank
)) {
205 //TODO 3 warn if this happens as such names should not have a wfo-id neither
213 * @return the WFO-ID of the taxon
215 private String
handleTaxon(WfoExportState state
, TaxonNode taxonNode
, String parentWfoId
) {
217 if (taxonNode
== null) {
218 state
.getResult().addError("The taxonNode was null.", "handleTaxon");
219 state
.getResult().setState(ExportResultState
.INCOMPLETE_WITH_ERROR
);
223 if (taxonNode
.getTaxon() == null) {
224 state
.getResult().addError("There was a taxon node without a taxon: " + taxonNode
.getUuid(),
226 state
.getResult().setState(ExportResultState
.INCOMPLETE_WITH_ERROR
);
230 //deproxy, just in case
231 Taxon taxon
= CdmBase
.deproxy(taxonNode
.getTaxon());
237 //classification csvLine
238 WfoExportTable table
= WfoExportTable
.CLASSIFICATION
;
239 String
[] csvLine
= new String
[table
.getSize()];
242 TaxonName name
= taxon
.getName();
243 wfoId
= handleName(state
, table
, csvLine
, name
);
245 //... parentNameUsageID
246 csvLine
[table
.getIndex(WfoExportTable
.TAX_PARENT_ID
)] = parentWfoId
;
249 csvLine
[table
.getIndex(WfoExportTable
.TAX_SUBFAMILY
)] = null;
250 csvLine
[table
.getIndex(WfoExportTable
.TAX_TRIBE
)] = null;
251 csvLine
[table
.getIndex(WfoExportTable
.TAX_SUBTRIBE
)] = null;
252 csvLine
[table
.getIndex(WfoExportTable
.TAX_SUBGENUS
)] = name
.isInfraGeneric()? name
.getInfraGenericEpithet() : null ;
254 //... tax status, TODO 2 are there other status for accepted or other reasons for being ambiguous
255 String taxonStatus
= taxon
.isDoubtful()?
"ambiguous" : "Accepted";
256 csvLine
[table
.getIndex(WfoExportTable
.TAX_STATUS
)] = taxonStatus
;
259 csvLine
[table
.getIndex(WfoExportTable
.NAME_ACCORDING_TO_ID
)] = getId(state
, taxon
.getSec());
260 if (taxon
.getSec() != null
261 && (!state
.getReferenceStore().contains((taxon
.getSec().getUuid())))) {
262 handleReference(state
, taxon
.getSec());
265 //TODO 2 remarks, what exactly
266 csvLine
[table
.getIndex(WfoExportTable
.TAXON_REMARKS
)] = getRemarks(name
);
268 handleSynonyms(state
, taxon
);
270 //TODO 2 taxon provisional, still an open issue?
271 // csvLine[table.getIndex(WfoExportTable.TAX_PROVISIONAL)] = taxonNode.isDoubtful() ? "1" : "0";
273 //TODO 1 taxon only published
276 state
.getProcessor().put(table
, taxon
, csvLine
);
278 } catch (Exception e
) {
280 state
.getResult().addException(e
,
281 "An unexpected problem occurred when trying to export taxon with id " + taxon
.getId() + " " + taxon
.getTitleCache());
282 state
.getResult().setState(ExportResultState
.INCOMPLETE_WITH_ERROR
);
289 private void handleSynonyms(WfoExportState state
, Taxon taxon
) {
290 //homotypic group / synonyms
291 HomotypicalGroup homotypicGroup
= taxon
.getHomotypicGroup();
292 handleHomotypicalGroup(state
, homotypicGroup
, taxon
);
293 for (Synonym syn
: taxon
.getSynonymsInGroup(homotypicGroup
)) {
294 handleSynonym(state
, syn
);
297 List
<HomotypicalGroup
> heterotypicHomotypicGroups
= taxon
.getHeterotypicSynonymyGroups();
298 for (HomotypicalGroup group
: heterotypicHomotypicGroups
){
299 handleHomotypicalGroup(state
, group
, taxon
);
300 for (Synonym syn
: taxon
.getSynonymsInGroup(group
)) {
301 handleSynonym(state
, syn
);
306 private boolean isUrl(String url
) {
308 if (url
.startsWith("http")) {
312 } catch (Exception e
) {
313 //exception should return false
318 private String
toIsoDate(TimePeriod mediaCreated
) {
319 //TODO 2 date, what if end or freetext exist?
320 Partial partial
= mediaCreated
.getStart();
321 if (partial
== null || !partial
.isSupported(DateTimeFieldType
.year())
322 || !partial
.isSupported(DateTimeFieldType
.monthOfYear()) && partial
.isSupported(DateTimeFieldType
.dayOfMonth())) {
323 //TODO 2 date, log warning, also if mediaCreated.getEnd() != null or so
326 DateTimeFormatter formatter
= new DateTimeFormatterBuilder()
327 .appendYear(4, 4).appendLiteral('-')
328 .appendMonthOfYear(2).appendLiteral('-')
331 return partial
.toString(formatter
);
336 * transforms the given date to an iso date
338 protected String
toIsoDate(DateTime dateTime
) {
339 if (dateTime
== null) {
342 DateTimeFormatter formatter
= new DateTimeFormatterBuilder()
343 .appendYear(4, 4).appendLiteral('-')
344 .appendMonthOfYear(2).appendLiteral('-')
347 return formatter
.print(dateTime
);
350 private String
getRemarks(AnnotatableEntity entity
) {
351 String remarks
= null;
352 for (Annotation a
: entity
.getAnnotations()) {
353 //TODO 3 handle other annotation types
354 if (AnnotationType
.EDITORIAL().equals(a
.getAnnotationType())
355 && CdmUtils
.isNotBlank(a
.getText())){
356 remarks
= CdmUtils
.concat(";", remarks
, a
.getText());
362 // private void handleMetaData(ColDpExportState state) {
363 // ColDpExportTable table = ColDpExportTable.METADATA;
364 // String[] csvLine = new String[table.getSize()];
365 //// csvLine[table.getIndex(CdmLightExportTable.INSTANCE_ID)] = state.getConfig().getInctanceId();
366 //// csvLine[table.getIndex(CdmLightExportTable.INSTANCE_NAME)] = state.getConfig().getInstanceName();
367 // csvLine[table.getIndex(ColDpExportTable.DATASET_BASE_URL)] = state.getConfig().getBase_url();
368 // csvLine[table.getIndex(ColDpExportTable.DATASET_CONTRIBUTOR)] = state.getConfig().getContributor();
369 // csvLine[table.getIndex(ColDpExportTable.DATASET_CREATOR)] = state.getConfig().getCreator();
370 // csvLine[table.getIndex(ColDpExportTable.DATASET_DESCRIPTION)] = state.getConfig().getDescription();
371 // csvLine[table.getIndex(ColDpExportTable.DATASET_DOWNLOAD_LINK)] = state.getConfig().getDataset_download_link();
372 // csvLine[table.getIndex(ColDpExportTable.DATASET_KEYWORDS)] = state.getConfig().getKeywords();
373 // csvLine[table.getIndex(ColDpExportTable.DATASET_LANDINGPAGE)] = state.getConfig().getDataSet_landing_page();
375 // csvLine[table.getIndex(ColDpExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
376 // csvLine[table.getIndex(ColDpExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
377 // csvLine[table.getIndex(ColDpExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
378 // csvLine[table.getIndex(ColDpExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
379 // csvLine[table.getIndex(ColDpExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
380 // state.getProcessor().put(table, "", csvLine);
383 private String
createMultilanguageString(Map
<Language
, LanguageString
> multilanguageText
) {
385 int index
= multilanguageText
.size();
386 for (LanguageString langString
: multilanguageText
.values()) {
387 text
+= langString
.getText();
396 private String
createAnnotationsString(Set
<Annotation
> annotations
) {
397 StringBuffer strBuff
= new StringBuffer();
399 for (Annotation ann
: annotations
) {
400 if (ann
.getAnnotationType() == null || !ann
.getAnnotationType().equals(AnnotationType
.TECHNICAL())) {
401 strBuff
.append(ann
.getText());
402 strBuff
.append("; ");
406 if (strBuff
.length() > 2) {
407 return strBuff
.substring(0, strBuff
.length() - 2);
413 private void handleSource(WfoExportState state
, DescriptionElementBase element
,
414 WfoExportTable factsTable
) {
415 // ColDpExportTable table = ColDpExportTable.FACT_SOURCES;
417 // Set<DescriptionElementSource> sources = element.getSources();
419 // for (DescriptionElementSource source : sources) {
420 // if (!(source.getType().equals(OriginalSourceType.Import)
421 // && state.getConfig().isExcludeImportSources())) {
422 // String[] csvLine = new String[table.getSize()];
423 // Reference ref = source.getCitation();
424 // if ((ref == null) && (source.getNameUsedInSource() == null)) {
427 // if (ref != null) {
428 // if (!state.getReferenceStore().contains(ref.getUuid())) {
429 // handleReference(state, ref);
432 // csvLine[table.getIndex(ColDpExportTable.REFERENCE_FK)] = getId(state, ref);
434 // csvLine[table.getIndex(ColDpExportTable.FACT_FK)] = getId(state, element);
436 // csvLine[table.getIndex(ColDpExportTable.NAME_IN_SOURCE_FK)] = getId(state,
437 // source.getNameUsedInSource());
438 // csvLine[table.getIndex(ColDpExportTable.FACT_TYPE)] = factsTable.getTableName();
439 // if (StringUtils.isBlank(csvLine[table.getIndex(ColDpExportTable.REFERENCE_FK)])
440 // && StringUtils.isBlank(csvLine[table.getIndex(ColDpExportTable.NAME_IN_SOURCE_FK)])) {
443 // state.getProcessor().put(table, source, csvLine);
446 // } catch (Exception e) {
447 // state.getResult().addException(e, "An unexpected error occurred when handling single source "
448 // + cdmBaseStr(element) + ": " + e.getMessage());
452 private String
getTitleCache(IIdentifiableEntity identEntity
) {
453 if (identEntity
== null) {
456 // TODO 3 titleCache refresh?
457 return identEntity
.getTitleCache();
460 private String
getId(WfoExportState state
, ICdmBase cdmBase
) {
461 if (cdmBase
== null) {
464 // TODO 4 id type, make configurable
465 return cdmBase
.getUuid().toString();
468 private void handleSynonym(WfoExportState state
, Synonym synonym
) {
470 if (isUnpublished(state
.getConfig(), synonym
)) {
474 WfoExportTable table
= WfoExportTable
.CLASSIFICATION
;
475 String
[] csvLine
= new String
[table
.getSize()];
477 TaxonName name
= synonym
.getName();
478 handleName(state
, table
, csvLine
, name
);
481 if (synonym
.getAcceptedTaxon()!= null && synonym
.getAcceptedTaxon().getName() != null) {
482 TaxonName acceptedName
= synonym
.getAcceptedTaxon().getName();
483 String acceptedWfoId
= getWfoId(state
, acceptedName
, false);
484 if (acceptedWfoId
== null) {
485 String message
= "WFO-ID for accepted name is missing. This should not happen. Synonym: " + name
.getTitleCache() + "; Accepted name: " + acceptedName
.getTitleCache();
486 state
.getResult().addError(message
, "handleName");
487 state
.getResult().setState(ExportResultState
.INCOMPLETE_WITH_ERROR
);
489 csvLine
[table
.getIndex(WfoExportTable
.TAX_ACCEPTED_NAME_ID
)] = acceptedWfoId
;
492 state
.getProcessor().put(table
, synonym
, csvLine
);
493 } catch (Exception e
) {
494 state
.getResult().addException(e
, "An unexpected error occurred when handling synonym "
495 + cdmBaseStr(synonym
) + ": " + e
.getMessage());
499 private String
handleName(WfoExportState state
, WfoExportTable table
, String
[] csvLine
,
502 name
= CdmBase
.deproxy(name
);
503 if (name
== null || state
.getNameStore().containsKey(name
.getId())) {
505 state
.getResult().addError("No name was given for taxon.", "handleName");
506 state
.getResult().setState(ExportResultState
.INCOMPLETE_WITH_ERROR
);
513 Rank rank
= name
.getRank();
514 state
.getNameStore().put(name
.getId(), name
.getUuid());
517 wfoId
= getWfoId(state
, name
, true);
518 if (isBlank(wfoId
)) {
519 String message
= "No WFO-ID given for taxon " + name
.getTitleCache() + ". Taxon ignored";
520 state
.getResult().addError(message
);
521 state
.getResult().setState(ExportResultState
.INCOMPLETE_WITH_ERROR
);
524 csvLine
[table
.getIndex(WfoExportTable
.TAXON_ID
)] = wfoId
;
527 //TODO 9 add IPNI ID if exists, scientific name ID
528 csvLine
[table
.getIndex(WfoExportTable
.NAME_SCIENTIFIC_NAME_ID
)] = null;
531 csvLine
[table
.getIndex(WfoExportTable
.NAME_LOCAL_ID
)] = getId(state
, name
);
534 if (name
.isProtectedTitleCache()) {
535 //TODO 7 make it configurable if we should always take titleCache if titleCache is protected, as nameCache may not necessarily
536 // have complete data if titleCache is protected as it is considered to be irrelevant or at least preliminary
538 if (StringUtils
.isNotEmpty(name
.getNameCache())) {
539 csvLine
[table
.getIndex(WfoExportTable
.NAME_SCIENTIFIC_NAME
)] = name
.getNameCache();
540 message
= "ScientificName: Name cache " + name
.getNameCache() + " used for name with protected titleCache " + name
.getTitleCache();
542 csvLine
[table
.getIndex(WfoExportTable
.NAME_SCIENTIFIC_NAME
)] = name
.getTitleCache();
543 message
= "ScientificName: Name has protected titleCache and no explicit nameCache: " + name
.getTitleCache();
545 state
.getResult().addWarning(message
); //TODO 7 add location to warning
547 csvLine
[table
.getIndex(WfoExportTable
.NAME_SCIENTIFIC_NAME
)] = name
.getNameCache();
551 String rankStr
= state
.getTransformer().getCacheByRank(rank
);
552 if (rankStr
== null) {
553 String message
= rank
== null ?
"No rank" : ("Rank not supported by WFO:" + rank
.getLabel())
554 + "Taxon not handled in export: " + name
.getTitleCache();
555 state
.getResult().addWarning(message
); //TODO 2 warning sufficient for missing rank? + location
558 csvLine
[table
.getIndex(WfoExportTable
.RANK
)] = rankStr
;
561 //TODO 3 handle empty authorship cache warning
562 csvLine
[table
.getIndex(WfoExportTable
.NAME_AUTHORSHIP
)] = name
.getAuthorshipCache();
564 //family TODO 2 family handling
565 csvLine
[table
.getIndex(WfoExportTable
.TAX_FAMILY
)] = state
.getFamilyStr();
568 csvLine
[table
.getIndex(WfoExportTable
.NAME_GENUS
)] = name
.isSupraGeneric()?
null : name
.getGenusOrUninomial();
569 csvLine
[table
.getIndex(WfoExportTable
.NAME_SPECIFIC_EPITHET
)] = name
.getSpecificEpithet();
570 csvLine
[table
.getIndex(WfoExportTable
.NAME_INFRASPECIFIC_EPITHET
)] = name
.getInfraSpecificEpithet();
572 //TODO 3 verbatimTaxonRank, is this needed at all?
573 csvLine
[table
.getIndex(WfoExportTable
.NAME_VERBATIM_RANK
)] = null;
576 csvLine
[table
.getIndex(WfoExportTable
.NAME_STATUS
)] = makeNameStatus(state
, name
);
579 String nomRef
= NomenclaturalSourceFormatter
.INSTANCE().format(name
.getNomenclaturalSource());
580 csvLine
[table
.getIndex(WfoExportTable
.NAME_PUBLISHED_IN
)] = nomRef
;
583 TaxonName originalName
= name
.getBasionym(); //TODO 5 basionym, order in case there are >1 basionyms
584 if (originalName
== null) {
585 originalName
= name
.getReplacedSynonyms().stream().findFirst().orElse(null);
588 if (originalName
!= null) {
589 if (!state
.getNameStore().containsKey(originalName
.getId())) {
590 //TODO 1 handle basionym is in file assertion
592 String basionymId
= getWfoId(state
, originalName
, false);
593 csvLine
[table
.getIndex(WfoExportTable
.NAME_ORIGINAL_NAME_ID
)] = basionymId
;
597 csvLine
[table
.getIndex(WfoExportTable
.CREATED
)] = null;
600 csvLine
[table
.getIndex(WfoExportTable
.MODIFIED
)] = null;
602 //TODO 1 URL to taxon
603 csvLine
[table
.getIndex(WfoExportTable
.REFERENCES
)] = null;
605 //TODO 3 excluded info
606 csvLine
[table
.getIndex(WfoExportTable
.EXCLUDE
)] = null;
608 //TODO 1 related names like orth. var., original spelling,
610 state
.getProcessor().put(table
, name
, csvLine
);
612 } catch (Exception e
) {
613 state
.getResult().addException(e
,
614 "An unexpected error occurred when handling the name " + cdmBaseStr(name
) + ": " + name
.getTitleCache() + ": " + e
.getMessage());
622 private String
getWfoId(WfoExportState state
, TaxonName name
, boolean warnIfNotExists
) {
623 Identifier wfoId
= name
.getIdentifier(IdentifierType
.uuidWfoNameIdentifier
);
624 if (wfoId
== null && warnIfNotExists
) {
625 String message
= "No wfo-id given for name: " + name
.getTitleCache()+"/"+ name
.getUuid();
626 state
.getResult().addWarning(message
); //TODO 5 data location
628 return wfoId
== null ?
null : wfoId
.getIdentifier();
631 private String
makeNameStatus(WfoExportState state
, TaxonName name
) {
634 //TODO 1 what is with dubium
635 if (name
.isLegitimate()) {
636 if (name
.isConserved()) {
641 } else if (name
.isRejected()) {
643 } else if (name
.isIllegitimate()) {
644 return "Illegitimate";
645 } else if (name
.isInvalid()) {
646 //TODO 2 handle original spellings for name status
647 if (name
.isOrthographicVariant()) {
648 return "orthografia";
653 String message
= "Unhandled name status case for name: " + name
.getTitleCache() +
654 ". Status not handled correctly.";
655 state
.getResult().addWarning(message
);
658 } catch (Exception e
) {
659 state
.getResult().addException(e
, "An unexpected error occurred when extracting status string for "
660 + cdmBaseStr(name
) + ": " + e
.getMessage());
665 private void handleHomotypicalGroup(WfoExportState state
, HomotypicalGroup group
, Taxon acceptedTaxon
) {
668 List
<TaxonName
> typifiedNames
= new ArrayList
<>();
669 if (acceptedTaxon
!= null){
670 List
<Synonym
> synonymsInGroup
= acceptedTaxon
.getSynonymsInGroup(group
);
671 if (group
.equals(acceptedTaxon
.getHomotypicGroup())){
672 typifiedNames
.add(acceptedTaxon
.getName());
674 synonymsInGroup
.stream().forEach(synonym
-> typifiedNames
.add(CdmBase
.deproxy(synonym
.getName())));
678 TaxonName firstname
= null;
679 for (TaxonName name
: typifiedNames
){
680 Iterator
<Taxon
> taxa
= name
.getTaxa().iterator();
681 while(taxa
.hasNext()){
682 Taxon taxon
= taxa
.next();
683 if(!(taxon
.isMisapplication() || taxon
.isProparteSynonym())){
690 } catch (Exception e
) {
691 state
.getResult().addException(e
, "An unexpected error occurred when handling homotypic group "
692 + cdmBaseStr(group
) + ": " + e
.getMessage());
696 private void handleReference(WfoExportState state
, Reference reference
) {
698 if (state
.getReferenceStore().contains(reference
.getUuid())) {
701 reference
= CdmBase
.deproxy(reference
);
703 state
.addReferenceToStore(reference
);
704 WfoExportTable table
= WfoExportTable
.REFERECE
;
705 String
[] csvLine
= new String
[table
.getSize()];
707 csvLine
[table
.getIndex(WfoExportTable
.IDENTIFIER
)] = getId(state
, reference
);
709 //TODO 2 correct?, ref biblio citation
710 csvLine
[table
.getIndex(WfoExportTable
.REF_BIBLIO_CITATION
)] = reference
.getCitation();
712 //TODO 1 uri (doi, uri or ext_link
713 // csvLine[table.getIndex(WfoExportTable.REF_DOI)] = reference.getDoiString();
715 // //TODO 2 reference link link (=> external link)
716 //// csvLine[table.getIndex(ColDpExportTable.LINK)] = null;
717 // if (reference.getUri() != null) {
718 // csvLine[table.getIndex(WfoExportTable.LINK)] = reference.getUri().toString();
721 state
.getProcessor().put(table
, reference
, csvLine
);
722 } catch (Exception e
) {
724 state
.getResult().addException(e
, "An unexpected error occurred when handling reference "
725 + cdmBaseStr(reference
) + ": " + e
.getMessage());
730 * Returns a string representation of the {@link CdmBase cdmBase} object for
733 private String
cdmBaseStr(CdmBase cdmBase
) {
734 if (cdmBase
== null) {
735 return "-no object available-";
737 return cdmBase
.getClass().getSimpleName() + ": " + cdmBase
.getUuid();
742 protected boolean doCheck(WfoExportState state
) {
747 protected boolean isIgnore(WfoExportState state
) {