ref #10446 remove duplicated missing wfo-id warning
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / coldp / ColDpClassificationExport.java
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.coldp;
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.joda.time.DateTime;
25 import org.joda.time.DateTimeFieldType;
26 import org.joda.time.Partial;
27 import org.joda.time.format.DateTimeFormatter;
28 import org.joda.time.format.DateTimeFormatterBuilder;
29 import org.springframework.stereotype.Component;
30
31 import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetComparator;
32 import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetContainer;
33 import eu.etaxonomy.cdm.common.CdmUtils;
34 import eu.etaxonomy.cdm.common.URI;
35 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
36 import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
37 import eu.etaxonomy.cdm.format.reference.OriginalSourceFormatter;
38 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
39 import eu.etaxonomy.cdm.io.cdmLight.OrderHelper;
40 import eu.etaxonomy.cdm.io.coldp.ColDpExportTransformer.ColDpNameRelType;
41 import eu.etaxonomy.cdm.io.common.CdmExportBase;
42 import eu.etaxonomy.cdm.io.common.ExportResult.ExportResultState;
43 import eu.etaxonomy.cdm.io.common.TaxonNodeOutStreamPartitioner;
44 import eu.etaxonomy.cdm.io.common.XmlExportState;
45 import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
46 import eu.etaxonomy.cdm.model.agent.AgentBase;
47 import eu.etaxonomy.cdm.model.agent.Person;
48 import eu.etaxonomy.cdm.model.agent.Team;
49 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
50 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
51 import eu.etaxonomy.cdm.model.common.Annotation;
52 import eu.etaxonomy.cdm.model.common.AnnotationType;
53 import eu.etaxonomy.cdm.model.common.CdmBase;
54 import eu.etaxonomy.cdm.model.common.ICdmBase;
55 import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
56 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
57 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
58 import eu.etaxonomy.cdm.model.common.Identifier;
59 import eu.etaxonomy.cdm.model.common.Language;
60 import eu.etaxonomy.cdm.model.common.LanguageString;
61 import eu.etaxonomy.cdm.model.common.TimePeriod;
62 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
63 import eu.etaxonomy.cdm.model.description.DescriptionBase;
64 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
65 import eu.etaxonomy.cdm.model.description.Distribution;
66 import eu.etaxonomy.cdm.model.description.Feature;
67 import eu.etaxonomy.cdm.model.description.TaxonDescription;
68 import eu.etaxonomy.cdm.model.description.TaxonInteraction;
69 import eu.etaxonomy.cdm.model.description.TextData;
70 import eu.etaxonomy.cdm.model.location.Country;
71 import eu.etaxonomy.cdm.model.location.NamedArea;
72 import eu.etaxonomy.cdm.model.location.Point;
73 import eu.etaxonomy.cdm.model.media.ExternalLink;
74 import eu.etaxonomy.cdm.model.media.Media;
75 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
76 import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
77 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
78 import eu.etaxonomy.cdm.model.name.NameRelationship;
79 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
80 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
81 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
82 import eu.etaxonomy.cdm.model.name.Rank;
83 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
84 import eu.etaxonomy.cdm.model.name.TaxonName;
85 import eu.etaxonomy.cdm.model.name.TextualTypeDesignation;
86 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
87 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
88 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
89 import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
90 import eu.etaxonomy.cdm.model.reference.IOriginalSource;
91 import eu.etaxonomy.cdm.model.reference.ISourceable;
92 import eu.etaxonomy.cdm.model.reference.Reference;
93 import eu.etaxonomy.cdm.model.taxon.Classification;
94 import eu.etaxonomy.cdm.model.taxon.Synonym;
95 import eu.etaxonomy.cdm.model.taxon.Taxon;
96 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
97 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
98 import eu.etaxonomy.cdm.model.term.IdentifierType;
99 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
100 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDtoByRankAndNameComparator;
101 import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
102 import eu.etaxonomy.cdm.strategy.cache.TagEnum;
103 import eu.etaxonomy.cdm.strategy.cache.TaggedText;
104
105 /**
106 * Classification or taxon tree exporter into COL-DP format.
107 * @author a.mueller
108 * @since 2023-07-17
109 */
110 @Component
111 public class ColDpClassificationExport
112 extends CdmExportBase<ColDpExportConfigurator,ColDpExportState,IExportTransformer,File>{
113
114 private static final long serialVersionUID = 4288364478648729869L;
115
116 public ColDpClassificationExport() {
117 this.ioName = this.getClass().getSimpleName();
118 }
119
120 @Override
121 public long countSteps(ColDpExportState state) {
122 TaxonNodeFilter filter = state.getConfig().getTaxonNodeFilter();
123 return getTaxonNodeService().count(filter);
124 }
125
126 @Override
127 protected void doInvoke(ColDpExportState state) {
128
129 try {
130 IProgressMonitor monitor = state.getConfig().getProgressMonitor();
131 ColDpExportConfigurator config = state.getConfig();
132
133 //set root node
134 if (config.getTaxonNodeFilter().hasClassificationFilter()) {
135 Classification classification = getClassificationService()
136 .load(config.getTaxonNodeFilter().getClassificationFilter().get(0).getUuid());
137 state.setRootId(classification.getRootNode().getUuid());
138 } else if (config.getTaxonNodeFilter().hasSubtreeFilter()) {
139 state.setRootId(config.getTaxonNodeFilter().getSubtreeFilter().get(0).getUuid());
140 }
141
142 @SuppressWarnings({ "unchecked", "rawtypes" })
143 TaxonNodeOutStreamPartitioner<XmlExportState> partitioner = TaxonNodeOutStreamPartitioner.NewInstance(this,
144 state, state.getConfig().getTaxonNodeFilter(), 100, monitor, null);
145
146 // handleMetaData(state); //FIXME metadata;
147 monitor.subTask("Start partitioning");
148
149 TaxonNode node = partitioner.next();
150 while (node != null) {
151 handleTaxonNode(state, node);
152 node = partitioner.next();
153 }
154
155 // get rootNode and create helperObjects
156 if (state.getRootId() != null) {
157 List<TaxonNodeDto> childrenOfRoot = state.getNodeChildrenMap().get(state.getRootId());
158
159 Comparator<TaxonNodeDto> comp = state.getConfig().getTaxonNodeComparator();
160 //FIXME comparator
161 if (comp == null) {
162 comp = new TaxonNodeDtoByRankAndNameComparator();
163 }
164 if (childrenOfRoot != null) {
165 Collections.sort(childrenOfRoot, comp);
166 OrderHelper helper = new OrderHelper(state.getRootId());
167 helper.setOrderIndex(state.getActualOrderIndexAndUpdate());
168 state.getOrderHelperMap().put(state.getRootId(), helper);
169
170 for (TaxonNodeDto child : childrenOfRoot) {
171 OrderHelper childHelper = new OrderHelper(child.getTaxonUuid());
172 helper.addChild(childHelper);
173 childHelper.setOrderIndex(state.getActualOrderIndexAndUpdate());
174 childHelper.addChildren(
175 createOrderHelper(state.getNodeChildrenMap().get(child.getUuid()), state));
176 }
177 }
178
179 state.getNodeChildrenMap().clear();
180 for (OrderHelper order : state.getOrderHelperMap().values()) {
181 setOrderIndex(state, order);
182 }
183 }
184
185 state.getProcessor().createFinalResult(state);
186 } catch (Exception e) {
187 state.getResult().addException(e,
188 "An unexpected error occurred in main method doInvoke() " + e.getMessage());
189 e.printStackTrace();
190 }
191 }
192
193 private void setOrderIndex(ColDpExportState state, OrderHelper order) {
194
195 if (order.getTaxonUuid() != null
196 && state.getProcessor().hasRecord(ColDpExportTable.TAXON, order.getTaxonUuid().toString())) {
197 String[] csvLine = state.getProcessor().getRecord(ColDpExportTable.TAXON,
198 order.getTaxonUuid().toString());
199 csvLine[ColDpExportTable.TAXON.getIndex(ColDpExportTable.TAX_SEQ_INDEX)] = String
200 .valueOf(order.getOrderIndex());
201 }
202
203 if (order.getChildren() == null) {
204 return;
205 }
206 for (OrderHelper helper : order.getChildren()) {
207 setOrderIndex(state, helper);
208 }
209 }
210
211 private List<OrderHelper> createOrderHelper(List<TaxonNodeDto> nodes, ColDpExportState state) {
212 List<TaxonNodeDto> children = nodes;
213 // alreadySortedNodes.add(parentUuid);
214 if (children == null) {
215 return null;
216 }
217 Comparator<TaxonNodeDto> comp = state.getConfig().getTaxonNodeComparator();
218 if (comp == null) {
219 comp = new TaxonNodeDtoByRankAndNameComparator();
220 }
221 Collections.sort(children, comp);
222 // TODO 3 taxon ordering: nochmal checken!!! - s.auch seq index
223 OrderHelper helperChild;
224 List<OrderHelper> childrenHelper = new ArrayList<>();
225 for (TaxonNodeDto child : children) {
226 helperChild = new OrderHelper(child.getTaxonUuid());
227 helperChild.setOrderIndex(state.getActualOrderIndexAndUpdate());
228
229 if (state.getNodeChildrenMap().get(child.getUuid()) != null) {
230 children = state.getNodeChildrenMap().get(child.getUuid());
231 helperChild.addChildren(createOrderHelper(children, state));
232 }
233 childrenHelper.add(helperChild);
234 }
235 return childrenHelper;
236 }
237
238 private void handleTaxonNode(ColDpExportState state, TaxonNode taxonNode) {
239
240 if (taxonNode == null) {
241 String message = "TaxonNode for given taxon node UUID not found. ";
242 // TODO 3 taxon node not found
243 state.getResult().addError(message);
244 } else {
245 try {
246 TaxonNode root = taxonNode;
247 List<TaxonNodeDto> childNodes;
248 if (root.hasChildNodes()) {
249 childNodes = new ArrayList<>();
250 for (TaxonNode child : root.getChildNodes()) {
251 if (child != null) {
252 childNodes.add(new TaxonNodeDto(child));
253 }
254 }
255 state.getNodeChildrenMap().put(root.getUuid(), childNodes);
256
257 // add root to node map
258 }
259 TaxonNodeDto rootDto = new TaxonNodeDto(root);
260 UUID parentUuid = root.getParent() != null ? root.getParent().getUuid()
261 : state.getClassificationUUID(root);
262 List<TaxonNodeDto> children = state.getNodeChildrenMap().get(parentUuid);
263 if (children != null && !children.contains(rootDto)) {
264 state.getNodeChildrenMap().get(parentUuid).add(rootDto);
265 } else if (state.getNodeChildrenMap().get(parentUuid) == null) {
266 List<TaxonNodeDto> rootList = new ArrayList<>();
267 rootList.add(rootDto);
268 state.getNodeChildrenMap().put(parentUuid, rootList);
269 }
270 if (root.hasTaxon()) {
271 handleTaxon(state, root);
272 }
273 } catch (Exception e) {
274 state.getResult().addException(e, "An unexpected error occurred when handling taxonNode "
275 + taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
276 }
277 }
278 }
279
280 private void handleTaxon(ColDpExportState state, TaxonNode taxonNode) {
281 //check null
282 if (taxonNode == null) {
283 state.getResult().addError("The taxonNode was null.", "handleTaxon");
284 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
285 return;
286 }
287 //check no taxon
288 if (taxonNode.getTaxon() == null) {
289 state.getResult().addError("There was a taxon node without a taxon: " + taxonNode.getUuid(),
290 "handleTaxon");
291 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
292 return;
293 }
294
295 try {
296
297 //handle taxon
298 Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon());
299 try {
300 //accepted name
301 TaxonName name = taxon.getName();
302 handleName(state, name, taxon, true);
303
304 if (state.getConfig().isDoSynonyms()) {
305 //homotypic group / synonyms
306 HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
307 int index = 0;
308 handleHomotypicalGroup(state, homotypicGroup, taxon);
309 for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
310 handleSynonym(state, syn, index);
311 index++;
312 }
313
314 List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
315 for (HomotypicalGroup group: heterotypicHomotypicGroups){
316 handleHomotypicalGroup(state, group, taxon);
317 for (Synonym syn : taxon.getSynonymsInGroup(group)) {
318 handleSynonym(state, syn, index);
319 index++;
320 }
321 }
322 }
323
324 //TODO 2 pro parte synonyms and misapplications
325 // //pro parte synonyms
326 // index = 0;
327 // for (Taxon tax : taxon.getAllProParteSynonyms()) {
328 // handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
329 // index++;
330 // }
331 //
332 // //misapplications
333 // for (Taxon tax : taxon.getAllMisappliedNames()) {
334 // handleProPartePartialMisapplied(state, tax, taxon, false, true, index);
335 // index++;
336 // }
337
338 //taxon table
339 ColDpExportTable table = ColDpExportTable.TAXON;
340 String[] csvLine = new String[table.getSize()];
341
342 csvLine[table.getIndex(ColDpExportTable.ID)] = getId(state, taxon);
343
344 //alternative IDs
345 handleAlternativeId(state, csvLine, table, taxon);
346
347 //TODO 9 sourceID //handled in referenceID
348 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
349
350 Taxon parent = (taxonNode.getParent() == null) ? null : taxonNode.getParent().getTaxon();
351 csvLine[table.getIndex(ColDpExportTable.TAX_PARENT_ID)] = getId(state, parent);
352
353 //TODO 5 seq index
354
355 //TODO 9 branchLength
356 csvLine[table.getIndex(ColDpExportTable.TAX_BRANCH_LENGTH)] = null;
357
358 //nameID
359 csvLine[table.getIndex(ColDpExportTable.TAX_NAME_ID)] = getId(state, name);
360
361 //TODO 6 namePhrase
362 csvLine[table.getIndex(ColDpExportTable.TAX_NAMEPHRASE)] = taxon.getAppendedPhrase();
363
364 //secundum reference
365 csvLine[table.getIndex(ColDpExportTable.TAX_SEC_ID)] = getId(state, taxon.getSec());
366 if (taxon.getSec() != null
367 && (!state.getReferenceStore().contains((taxon.getSec().getUuid())))) {
368 handleReference(state, taxon.getSec());
369 }
370
371 //TODO 4 SCRUTINIZER
372 //TODO 4 SCRUTINIZER ID
373 //TODO 4 SCRUTINIZER Date
374
375 //TODO 2 taxon provisional, still an open issue?
376 csvLine[table.getIndex(ColDpExportTable.TAX_PROVISIONAL)] = taxonNode.isDoubtful() ? "1" : "0";
377
378 //reference ID
379 handleReference(state, csvLine, table, taxon);
380
381 //TODO 3 taxon extinct
382
383 //TODO 7 taxon temporalRangeStart
384 csvLine[table.getIndex(ColDpExportTable.TAX_TEMPORAL_RANGE_END)] = null;
385 //TODO 7 taxon temporalRangeEnd
386 csvLine[table.getIndex(ColDpExportTable.TAX_TEMPORAL_RANGE_END)] = null;
387
388 //TODO 5 taxon environment
389 csvLine[table.getIndex(ColDpExportTable.TAX_ENVIRONMENT)] = null;
390
391 //TODO 6 taxon species, section, subgenus, genus, ... - can be null if parent ID is given
392
393 //remarks
394 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = getRemarks(taxon);
395
396 //TODO 1 taxon only published
397
398 //process taxon line
399 state.getProcessor().put(table, taxon, csvLine);
400
401 //descriptions
402 handleDescriptions(state, taxon);
403
404 //media
405 handleMedia(state, taxon);
406
407 } catch (Exception e) {
408 e.printStackTrace();
409 state.getResult().addException(e,
410 "An unexpected problem occurred when trying to export taxon with id " + taxon.getId() + " " + taxon.getTitleCache());
411 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
412 }
413 } catch (Exception e) {
414 state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
415 + cdmBaseStr(taxonNode.getTaxon()) + ", titleCache:"+ taxonNode.getTaxon().getTitleCache()+": " + e.getMessage());
416 }
417 }
418
419 private void handleAlternativeId(ColDpExportState state, String[] csvLine, ColDpExportTable table, IdentifiableEntity<?> entity) {
420 String alternativeIdStr = null;
421
422 for (Identifier identifier : entity.getIdentifiers()) {
423 //TODO 4 alternativeID filter Identifiers
424 IdentifierType type = identifier.getType();
425 String prefix = null;
426 String value = identifier.getIdentifier();
427 String url = identifier.getUrl();
428 if (type != null) {
429 //TODO 4 alternativeID handle other identifier types
430 if (type.equals(IdentifierType.IDENTIFIER_NAME_WFO())) {
431 prefix = "wfo";
432 value = value.replace("wfo-", "");
433 }
434 }else if (url != null && !url.isEmpty() && isUrl(url)) {
435 value = url;
436 }else {
437 //TODO 4 alternativeID log failing identifier
438 }
439 alternativeIdStr = CdmUtils.concat(",", alternativeIdStr, CdmUtils.concat(":", prefix, value));
440 }
441
442 csvLine[table.getIndex(ColDpExportTable.ALTERNATIVE_ID)] = alternativeIdStr;
443 }
444
445 private boolean isUrl(String url) {
446 try {
447 if (url.startsWith("http")) {
448 URI.fromString(url);
449 return true;
450 }
451 } catch (Exception e) {
452 //exception should return false
453 }
454 return false;
455 }
456
457 private void handleMedia(ColDpExportState state, Taxon taxon) {
458 Set<Media> mediaSet = new HashSet<>();
459
460 //TODO 3 media collect media form other places
461
462 //collect from taxon image gallery
463 Set<? extends DescriptionBase<?>> descriptions = taxon.getDescriptions();
464 for (DescriptionBase<?> description : descriptions){
465 for (DescriptionElementBase o : description.getElements()){
466 DescriptionElementBase el = CdmBase.deproxy(o);
467 if (el.getMedia().size() > 0){
468 for (Media media: el.getMedia()){
469 mediaSet.add(media);
470 }
471 }
472 }
473 }
474
475 //handle single media
476 for (Media media : mediaSet) {
477 for (MediaRepresentation repr : media.getRepresentations()){
478 for (MediaRepresentationPart part : repr.getParts()){
479 handleMediaRepresentation(state, taxon, part);
480 }
481 }
482 }
483 }
484
485 private void handleMediaRepresentation(ColDpExportState state, Taxon taxon, MediaRepresentationPart part) {
486 if (part == null || state.getMediaStore().contains(part.getUuid())) {
487 return;
488 }
489
490 state.addMediaToStore(part);
491 ColDpExportTable table = ColDpExportTable.MEDIA;
492 String[] csvLine = new String[table.getSize()];
493 part = HibernateProxyHelper.deproxy(part);
494
495 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, taxon);
496
497 //TODO 9 media sourceID //handled in referenceID
498 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
499
500 //url
501 if (part.getUri() != null) {
502 csvLine[table.getIndex(ColDpExportTable.MEDIA_URL)] = part.getUri().toString();
503 }
504
505 //TODO 3 media type, still open?
506 csvLine[table.getIndex(ColDpExportTable.TYPE)] = part.getMediaRepresentation().getMimeType();
507
508 //TODO 3 media format
509 csvLine[table.getIndex(ColDpExportTable.MEDIA_FORMAT)] = null;
510
511 Media media = part.getMediaRepresentation().getMedia();
512
513 //title
514 csvLine[table.getIndex(ColDpExportTable.MEDIA_TITLE)] = getTitleCache(media);
515
516 //created
517 csvLine[table.getIndex(ColDpExportTable.MEDIA_CREATED)] = toIsoDate(media.getMediaCreated());
518
519 //creator //TODO 3 media format creator
520 csvLine[table.getIndex(ColDpExportTable.MEDIA_CREATOR)] = getTitleCache(media.getArtist());
521
522 //TODO 5 media license
523 csvLine[table.getIndex(ColDpExportTable.MEDIA_LICENSE)] = null;
524
525 //TODO 5 media link
526 csvLine[table.getIndex(ColDpExportTable.LINK)] = null;
527
528 state.getProcessor().put(table, part, csvLine);
529 }
530
531 private String toIsoDate(TimePeriod mediaCreated) {
532 if (mediaCreated == null) {
533 return null;
534 }
535 //TODO 2 date, what if end or freetext exist?
536 Partial partial = mediaCreated.getStart();
537 if (partial == null || !partial.isSupported(DateTimeFieldType.year())
538 || !partial.isSupported(DateTimeFieldType.monthOfYear()) && partial.isSupported(DateTimeFieldType.dayOfMonth())) {
539 //TODO 2 date, log warning, also if mediaCreated.getEnd() != null or so
540 return null;
541 } else {
542 DateTimeFormatter formatter = new DateTimeFormatterBuilder()
543 .appendYear(4, 4).appendLiteral('-')
544 .appendMonthOfYear(2).appendLiteral('-')
545 .appendDayOfMonth(2)
546 .toFormatter();
547 return partial.toString(formatter);
548 }
549 }
550
551 /**
552 * transforms the given date to an iso date
553 */
554 protected String toIsoDate(DateTime dateTime) {
555 if (dateTime == null) {
556 return null;
557 }
558 DateTimeFormatter formatter = new DateTimeFormatterBuilder()
559 .appendYear(4, 4).appendLiteral('-')
560 .appendMonthOfYear(2).appendLiteral('-')
561 .appendDayOfMonth(2)
562 .toFormatter();
563 return formatter.print(dateTime);
564 }
565
566 private void handleDescriptions(ColDpExportState state, Taxon taxon) {
567 if (!state.getConfig().isDoFactualData()) {
568 return;
569 }
570 String titleCache = null;
571 try {
572 taxon = HibernateProxyHelper.deproxy(taxon);
573 titleCache = taxon.getTitleCache();
574 Set<TaxonDescription> descriptions = taxon.getDescriptions();
575 List<DescriptionElementBase> distributionFacts = new ArrayList<>();
576 List<DescriptionElementBase> taxonInteractionsFacts = new ArrayList<>();
577 List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
578 for (TaxonDescription description : descriptions) {
579 if (description.getElements() != null &&
580 description.isPublish() || state.getConfig().isIncludeUnpublishedFacts()){
581 for (DescriptionElementBase element : description.getElements()) {
582 element = CdmBase.deproxy(element);
583 if (element.getFeature().equals(Feature.COMMON_NAME())) {
584 commonNameFacts.add(element);
585 } else if (element.getFeature().equals(Feature.DISTRIBUTION())) {
586 distributionFacts.add(element);
587 } else if (element.getFeature().isSupportsTaxonInteraction()) {
588 taxonInteractionsFacts.add(element);
589 } else {
590 //ignore
591 }
592 }
593 }
594 }
595 if (!commonNameFacts.isEmpty()) {
596 handleCommonNameFacts(state, taxon, commonNameFacts);
597 }
598 if (!distributionFacts.isEmpty()) {
599 handleDistributionFacts(state, taxon, distributionFacts);
600 }
601 if (!taxonInteractionsFacts.isEmpty()) {
602 handleTaxonInteractionsFacts(state, taxon, taxonInteractionsFacts);
603 }
604 } catch (Exception e) {
605 state.getResult().addException(e, "An unexpected error occurred when handling description of "
606 + cdmBaseStr(taxon) + (titleCache != null? (" " +titleCache) : "")+": " + e.getMessage());
607 }
608 }
609
610 private String getRemarks(AnnotatableEntity entity) {
611 String remarks = null;
612 for (Annotation a : entity.getAnnotations()) {
613 //TODO 3 handle other annotation types
614 if (AnnotationType.EDITORIAL().equals(a.getAnnotationType())
615 && CdmUtils.isNotBlank(a.getText())){
616 remarks = CdmUtils.concat(";", remarks, a.getText());
617 }
618 }
619 return remarks;
620 }
621
622 // private void handleMetaData(ColDpExportState state) {
623 // ColDpExportTable table = ColDpExportTable.METADATA;
624 // String[] csvLine = new String[table.getSize()];
625 //// csvLine[table.getIndex(CdmLightExportTable.INSTANCE_ID)] = state.getConfig().getInctanceId();
626 //// csvLine[table.getIndex(CdmLightExportTable.INSTANCE_NAME)] = state.getConfig().getInstanceName();
627 // csvLine[table.getIndex(ColDpExportTable.DATASET_BASE_URL)] = state.getConfig().getBase_url();
628 // csvLine[table.getIndex(ColDpExportTable.DATASET_CONTRIBUTOR)] = state.getConfig().getContributor();
629 // csvLine[table.getIndex(ColDpExportTable.DATASET_CREATOR)] = state.getConfig().getCreator();
630 // csvLine[table.getIndex(ColDpExportTable.DATASET_DESCRIPTION)] = state.getConfig().getDescription();
631 // csvLine[table.getIndex(ColDpExportTable.DATASET_DOWNLOAD_LINK)] = state.getConfig().getDataset_download_link();
632 // csvLine[table.getIndex(ColDpExportTable.DATASET_KEYWORDS)] = state.getConfig().getKeywords();
633 // csvLine[table.getIndex(ColDpExportTable.DATASET_LANDINGPAGE)] = state.getConfig().getDataSet_landing_page();
634 //
635 // csvLine[table.getIndex(ColDpExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
636 // csvLine[table.getIndex(ColDpExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
637 // csvLine[table.getIndex(ColDpExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
638 // csvLine[table.getIndex(ColDpExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
639 // csvLine[table.getIndex(ColDpExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
640 // state.getProcessor().put(table, "", csvLine);
641 // }
642
643 private void handleTaxonInteractionsFacts(ColDpExportState state, CdmBase cdmBase,
644 List<DescriptionElementBase> taxonInteractionsFacts) {
645
646 ColDpExportTable table = ColDpExportTable.SPECIES_INTERACTION;
647 String titleCache = null;
648 if (cdmBase instanceof TaxonBase){
649 titleCache = ((TaxonBase)cdmBase).getTitleCache();
650 }
651 for (DescriptionElementBase element : taxonInteractionsFacts) {
652
653 try {
654
655 String[] csvLine = new String[table.getSize()];
656
657 // csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, element);
658 handleSource(state, element, table);
659 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, cdmBase);
660 csvLine[table.getIndex(ColDpExportTable.REL_TAXON_TAXON_ID)] = getId(state,
661 ((TaxonInteraction) element).getTaxon2());
662 //TODO 5 taxon interaction Scentific name for species interaction
663 //TODO 2 taxon interaction, why does this handling from other remarks handling?
664 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = createMultilanguageString(
665 ((TaxonInteraction) element).getDescription());
666 state.getProcessor().put(table, element, csvLine);
667
668 } catch (Exception e) {
669 state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
670 + cdmBaseStr(element) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
671 }
672 }
673 }
674
675 private void handleSimpleMediaFact(ColDpExportState state, Taxon taxon, ColDpExportTable table,
676 DescriptionElementBase element) {
677 try {
678 String[] csvLine;
679 handleSource(state, element, ColDpExportTable.MEDIA);
680
681 if (element instanceof TextData) {
682 TextData textData = (TextData) element;
683 csvLine = new String[table.getSize()];
684 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, taxon);
685
686 String mediaUris = "";
687 for (Media media : textData.getMedia()) {
688 String mediaString = extractMediaUris(media.getRepresentations().iterator());
689 if (!StringUtils.isBlank(mediaString)) {
690 mediaUris += mediaString + ";";
691 } else {
692 state.getResult().addWarning("Empty Media object for " + taxon.getUserFriendlyTypeName() + " "
693 + taxon.getUuid() + " (media: " + media.getUuid() + ")");
694 }
695 }
696 csvLine[table.getIndex(ColDpExportTable.MEDIA_URL)] = mediaUris;
697 //TODO 2 media title, type (MIME-type), what is meant here?
698 csvLine[table.getIndex(ColDpExportTable.MEDIA_TITLE)] = mediaUris;
699 }
700 } catch (Exception e) {
701 state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
702 + cdmBaseStr(element) + ": " + e.getMessage());
703 }
704
705 }
706
707 private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
708 String text = "";
709 int index = multilanguageText.size();
710 for (LanguageString langString : multilanguageText.values()) {
711 text += langString.getText();
712 if (index > 1) {
713 text += "; ";
714 }
715 index--;
716 }
717 return text;
718 }
719
720 private String createAnnotationsString(Set<Annotation> annotations) {
721 StringBuffer strBuff = new StringBuffer();
722
723 for (Annotation ann : annotations) {
724 if (ann.getAnnotationType() == null || !ann.getAnnotationType().equals(AnnotationType.TECHNICAL())) {
725 strBuff.append(ann.getText());
726 strBuff.append("; ");
727 }
728 }
729
730 if (strBuff.length() > 2) {
731 return strBuff.substring(0, strBuff.length() - 2);
732 } else {
733 return null;
734 }
735 }
736
737 private void handleSource(ColDpExportState state, DescriptionElementBase element,
738 ColDpExportTable factsTable) {
739 // ColDpExportTable table = ColDpExportTable.FACT_SOURCES;
740 // try {
741 // Set<DescriptionElementSource> sources = element.getSources();
742 //
743 // for (DescriptionElementSource source : sources) {
744 // if (!(source.getType().equals(OriginalSourceType.Import)
745 // && state.getConfig().isExcludeImportSources())) {
746 // String[] csvLine = new String[table.getSize()];
747 // Reference ref = source.getCitation();
748 // if ((ref == null) && (source.getNameUsedInSource() == null)) {
749 // continue;
750 // }
751 // if (ref != null) {
752 // if (!state.getReferenceStore().contains(ref.getUuid())) {
753 // handleReference(state, ref);
754 //
755 // }
756 // csvLine[table.getIndex(ColDpExportTable.REFERENCE_FK)] = getId(state, ref);
757 // }
758 // csvLine[table.getIndex(ColDpExportTable.FACT_FK)] = getId(state, element);
759 //
760 // csvLine[table.getIndex(ColDpExportTable.NAME_IN_SOURCE_FK)] = getId(state,
761 // source.getNameUsedInSource());
762 // csvLine[table.getIndex(ColDpExportTable.FACT_TYPE)] = factsTable.getTableName();
763 // if (StringUtils.isBlank(csvLine[table.getIndex(ColDpExportTable.REFERENCE_FK)])
764 // && StringUtils.isBlank(csvLine[table.getIndex(ColDpExportTable.NAME_IN_SOURCE_FK)])) {
765 // continue;
766 // }
767 // state.getProcessor().put(table, source, csvLine);
768 // }
769 // }
770 // } catch (Exception e) {
771 // state.getResult().addException(e, "An unexpected error occurred when handling single source "
772 // + cdmBaseStr(element) + ": " + e.getMessage());
773 // }
774 }
775
776 private void handleDistributionFacts(ColDpExportState state, Taxon taxon,
777 List<DescriptionElementBase> distributionFacts) {
778
779 ColDpExportTable table = ColDpExportTable.DISTRIBUTION;
780 Set<Distribution> distributions = new HashSet<>();
781 for (DescriptionElementBase element : distributionFacts) {
782 try {
783 //TODO 3 distribution also check feature
784 if (element instanceof Distribution) {
785 String[] csvLine = new String[table.getSize()];
786 Distribution distribution = (Distribution) element;
787 distributions.add(distribution);
788
789 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, taxon);
790
791 NamedArea area = CdmBase.deproxy(distribution.getArea());
792 if (area != null) {
793 String gazetteer = "text";
794 String areaID = null;
795 if (area.getClass().equals(Country.class)) {
796 Country country = CdmBase.deproxy(area, Country.class);
797 areaID = country.getIdInVocabulary();
798 gazetteer = "iso";
799 } else if (NamedArea.isTdwgArea(area)) {
800 gazetteer = "tdwg";
801 areaID = area.getIdInVocabulary();
802 }
803
804 //areaID
805 csvLine[table.getIndex(ColDpExportTable.DIST_AREA_ID)] = areaID;
806
807 //area
808 //TODO 3 distribution area, does this always use the full English? Looks like this is not true for countries.
809 csvLine[table.getIndex(ColDpExportTable.DIST_AREA)] = area.getLabel();
810
811 //gazetteer
812 csvLine[table.getIndex(ColDpExportTable.DIST_GAZETTEER)] = gazetteer;
813 }
814
815 if (distribution.getStatus() != null) {
816 csvLine[table.getIndex(ColDpExportTable.DIST_STATUS)]
817 = state.getTransformer().getCacheByPresenceAbsenceTerm(distribution.getStatus());
818 }
819
820 //reference ID
821 handleReference(state, csvLine, table, distribution);
822
823 //remarks
824 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = getRemarks(distribution);
825
826 state.getProcessor().put(table, distribution, csvLine);
827 } else {
828 state.getResult()
829 .addError("The distribution description for the taxon " + taxon.getUuid()
830 + " is not of type distribution. Could not be exported. UUID of the description element: "
831 + element.getUuid());
832 }
833 } catch (Exception e) {
834 e.printStackTrace();
835 state.getResult().addException(e, "An unexpected error occurred when handling single distribution "
836 + cdmBaseStr(element) + ": " + e.getMessage());
837 }
838 }
839 }
840
841 private void handleCommonNameFacts(ColDpExportState state, Taxon taxon,
842 List<DescriptionElementBase> commonNameFacts) {
843 ColDpExportTable table = ColDpExportTable.VERNACULAR_NAME;
844
845 for (DescriptionElementBase element : commonNameFacts) {
846 try {
847 if (element instanceof CommonTaxonName) {
848 String[] csvLine = new String[table.getSize()];
849 CommonTaxonName commonName = (CommonTaxonName) element;
850 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, taxon);
851 if (commonName.getName() != null) {
852 csvLine[table.getIndex(ColDpExportTable.VERN_NAME)] = commonName.getName();
853 }
854
855 //transliteration - we do not have this yet
856 csvLine[table.getIndex(ColDpExportTable.VERN_TRANSLITERATION)] = commonName.getTransliteration();
857
858 if (commonName.getLanguage() != null) {
859 //TODO 2 common name char(3) lang
860 csvLine[table.getIndex(ColDpExportTable.VERN_LANGUAGE)] = commonName.getLanguage().getIso639_2();
861 }
862
863 //TODO 2 common name country
864
865 if (commonName.getArea() != null) {
866 csvLine[table.getIndex(ColDpExportTable.VERN_AREA)] = commonName.getArea().getLabel();
867 }
868
869 //sex - we do not have this yet
870 csvLine[table.getIndex(ColDpExportTable.VERN_SEX)] = null;
871
872 //referenceID
873 handleReference(state, csvLine, table, commonName);
874
875 state.getProcessor().put(table, commonName, csvLine);
876 } else if (element instanceof TextData){
877 String[] csvLine = new String[table.getSize()];
878 TextData commonName = (TextData) element;
879 handleSource(state, element, table);
880 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, taxon);
881 if (commonName.getMultilanguageText() != null) {
882 csvLine[table.getIndex(ColDpExportTable.VERN_NAME)] = createMultilanguageString(commonName.getMultilanguageText());
883 }
884 state.getProcessor().put(table, commonName, csvLine);
885 } else {
886 state.getResult()
887 .addError("The common name description for the taxon " + taxon.getUuid()
888 + " is not of type common name. Could not be exported. UUID of the description element: "
889 + element.getUuid());
890 }
891 } catch (Exception e) {
892 state.getResult().addException(e, "An unexpected error occurred when handling single common name "
893 + cdmBaseStr(element) + " - "+taxon.getTitleCache()+ ": " + e.getMessage());
894 }
895 }
896 }
897
898 private String getTitleCache(IIdentifiableEntity identEntity) {
899 if (identEntity == null) {
900 return "";
901 }
902 // TODO 3 titleCache refresh?
903 return identEntity.getTitleCache();
904 }
905
906 private String getId(ColDpExportState state, ICdmBase cdmBase) {
907 if (cdmBase == null) {
908 return "";
909 }
910 // TODO 4 id type, make configurable
911 return cdmBase.getUuid().toString();
912 }
913
914 private void handleSynonym(ColDpExportState state, Synonym synonym, int index) {
915 try {
916 if (isUnpublished(state.getConfig(), synonym)) {
917 return;
918 }
919 TaxonName name = synonym.getName();
920 handleName(state, name, synonym.getAcceptedTaxon());
921
922 ColDpExportTable table = ColDpExportTable.SYNONYM;
923 String[] csvLine = new String[table.getSize()];
924
925 csvLine[table.getIndex(ColDpExportTable.ID)] = getId(state, synonym);
926
927 //TODO 9 synonym sourceID //handled in referenceID and sec_ID
928 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
929
930 csvLine[table.getIndex(ColDpExportTable.TAXON_ID)] = getId(state, synonym.getAcceptedTaxon());
931 csvLine[table.getIndex(ColDpExportTable.TAX_NAME_ID)] = getId(state, name);
932 if (synonym.getSec() != null && !state.getReferenceStore().contains(synonym.getSec().getUuid())) {
933 handleReference(state, synonym.getSec());
934 csvLine[table.getIndex(ColDpExportTable.REFERENCE_ID)] = getId(state, synonym.getSec());
935 }
936 csvLine[table.getIndex(ColDpExportTable.TAX_NAMEPHRASE)] = synonym.getAppendedPhrase();
937 csvLine[table.getIndex(ColDpExportTable.TAX_SEC_ID)] = getId(state, synonym.getSec());
938
939 state.getProcessor().put(table, synonym, csvLine);
940 } catch (Exception e) {
941 state.getResult().addException(e, "An unexpected error occurred when handling synonym "
942 + cdmBaseStr(synonym) + ": " + e.getMessage());
943 }
944 }
945
946 // /**
947 // * Handles misapplied names (including pro parte and partial as well as pro
948 // * parte and partial synonyms
949 // */
950 // private void handleProPartePartialMisapplied(ColDpExportState state, Taxon taxon, Taxon accepted, boolean isProParte, boolean isMisapplied, int index) {
951 // try {
952 // Taxon ppSyonym = taxon;
953 // if (isUnpublished(state.getConfig(), ppSyonym)) {
954 // return;
955 // }
956 // TaxonName name = ppSyonym.getName();
957 // handleName(state, name, accepted);
958 //
959 // ColDpExportTable table = ColDpExportTable.SYNONYM;
960 // String[] csvLine = new String[table.getSize()];
961 //
962 // csvLine[table.getIndex(ColDpExportTable.SYNONYM_ID)] = getId(state, ppSyonym);
963 // csvLine[table.getIndex(ColDpExportTable.TAXON_FK)] = getId(state, accepted);
964 // csvLine[table.getIndex(ColDpExportTable.NAME_FK)] = getId(state, name);
965 //
966 // Reference secRef = ppSyonym.getSec();
967 //
968 // if (secRef != null && !state.getReferenceStore().contains(secRef.getUuid())) {
969 // handleReference(state, secRef);
970 // }
971 // csvLine[table.getIndex(ColDpExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
972 // csvLine[table.getIndex(ColDpExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
973 // Set<TaxonRelationship> rels = accepted.getTaxonRelations(ppSyonym);
974 // TaxonRelationship rel = null;
975 // boolean isPartial = false;
976 // if (rels.size() == 1){
977 // rel = rels.iterator().next();
978 //
979 // }else if (rels.size() > 1){
980 // Iterator<TaxonRelationship> iterator = rels.iterator();
981 // while (iterator.hasNext()){
982 // rel = iterator.next();
983 // if (isProParte && rel.getType().isAnySynonym()){
984 // break;
985 // } else if (isMisapplied && rel.getType().isAnyMisappliedName()){
986 // break;
987 // }else{
988 // rel = null;
989 // }
990 // }
991 // }
992 // if (rel != null){
993 // Reference synSecRef = rel.getCitation();
994 // if (synSecRef != null && !state.getReferenceStore().contains(synSecRef.getUuid())) {
995 // handleReference(state, synSecRef);
996 // }
997 // csvLine[table.getIndex(ColDpExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
998 // csvLine[table.getIndex(ColDpExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
999 // isProParte = rel.getType().isProParte();
1000 // isPartial = rel.getType().isPartial();
1001 //
1002 // }else{
1003 // state.getResult().addWarning("An unexpected error occurred when handling "
1004 // + "pro parte/partial synonym or misapplied name " + cdmBaseStr(taxon) );
1005 // }
1006 //
1007 // // pro parte type
1008 //
1009 // csvLine[table.getIndex(ColDpExportTable.IS_PRO_PARTE)] = isProParte ? "1" : "0";
1010 // csvLine[table.getIndex(ColDpExportTable.IS_PARTIAL)] = isPartial ? "1" : "0";
1011 // csvLine[table.getIndex(ColDpExportTable.IS_MISAPPLIED)] = isMisapplied ? "1" : "0";
1012 // csvLine[table.getIndex(ColDpExportTable.SORT_INDEX)] = String.valueOf(index);
1013 // state.getProcessor().put(table, ppSyonym, csvLine);
1014 // } catch (Exception e) {
1015 // state.getResult().addException(e, "An unexpected error occurred when handling "
1016 // + "pro parte/partial synonym or misapplied name " + cdmBaseStr(taxon) + ": " + e.getMessage());
1017 // }
1018 // }
1019
1020 private void handleName(ColDpExportState state, TaxonName name, Taxon acceptedTaxon){
1021 handleName(state, name, acceptedTaxon, false);
1022 }
1023
1024 private void handleName(ColDpExportState state, TaxonName name, Taxon acceptedTaxon, boolean acceptedName) {
1025 if (name == null || state.getNameStore().containsKey(name.getId())) {
1026 return;
1027 }
1028 try {
1029 //TODO is there a better way to handle configurable columns? #10451
1030 ColDpExportTable table = state.getConfig().isIncludeFullName() ? ColDpExportTable.NAME_WITH_FULLNAME :
1031 ColDpExportTable.NAME;
1032
1033 String[] csvLine = new String[table.getSize()];
1034
1035 Rank rank = name.getRank();
1036 name = HibernateProxyHelper.deproxy(name);
1037 state.getNameStore().put(name.getId(), name.getUuid());
1038
1039 csvLine[table.getIndex(ColDpExportTable.ID)] = getId(state, name);
1040
1041 //TODO 3 name, handle LSIDs
1042 // if (name.getLsid() != null) {
1043 // csvLine[table.getIndex(ColDpExportTable.LSID)] = name.getLsid().getLsid();
1044 // } else {
1045 // csvLine[table.getIndex(ColDpExportTable.LSID)] = "";
1046 // }
1047 handleAlternativeId(state, csvLine, table, name);
1048
1049 //TODO 9 name sourceID
1050 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
1051
1052 //basionymID
1053 TaxonName basionym = name.getBasionym(); //TODO 5 basionym, order in case there are >1 basionyms
1054 if (basionym != null) {
1055 if (!state.getNameStore().containsKey(basionym.getId())) {
1056 handleName(state, basionym, null);
1057 }
1058 csvLine[table.getIndex(ColDpExportTable.NAME_BASIONYM_ID)] = getId(state, basionym);
1059 }
1060
1061 //scientificName
1062 if (name.isProtectedTitleCache() && StringUtils.isEmpty(name.getNameCache())) {
1063 //TODO 7 make it configurable if we should always take titleCache if titleCache is protected, as nameCache may not necessarily have complete data if titleCache is protected as it is considered to be irrelevant or at least preliminary
1064 String message = "";
1065 if (StringUtils.isEmpty(name.getNameCache())) {
1066 csvLine[table.getIndex(ColDpExportTable.NAME_SCIENTIFIC_NAME)] = name.getNameCache();
1067 message = "ScientificName: Name cache " + name.getNameCache() + " used for name with protected titleCache " + name.getTitleCache();
1068 }else {
1069 csvLine[table.getIndex(ColDpExportTable.NAME_SCIENTIFIC_NAME)] = name.getTitleCache();
1070 message = "ScientificName: Name has protected titleCache and no explicit nameCache: " + name.getTitleCache();
1071 }
1072 state.getResult().addWarning(message); //TODO 7 add location to warning
1073 } else {
1074 csvLine[table.getIndex(ColDpExportTable.NAME_SCIENTIFIC_NAME)] = name.getNameCache();
1075 }
1076 if (state.getConfig().isIncludeFullName()) {
1077 csvLine[table.getIndex(ColDpExportTable.NAME_FULLNAME)] = name.getTitleCache();
1078 }
1079
1080 //authorship
1081 csvLine[table.getIndex(ColDpExportTable.NAME_AUTHORSHIP)] = name.getAuthorshipCache();
1082 //combinationAuthorship
1083 csvLine[table.getIndex(ColDpExportTable.NAME_COMBINATION_AUTHORSHIP)] = teamToString(name.getCombinationAuthorship());
1084 //combinationExAuthorship
1085 csvLine[table.getIndex(ColDpExportTable.NAME_COMBINATION_EX_AUTHORSHIP)] = teamToString(name.getExCombinationAuthorship());
1086 //combinationAuthorshipYear
1087 csvLine[table.getIndex(ColDpExportTable.NAME_COMBINATION_AUTHORSHIP_YEAR)] = name.getNomenclaturalReference() == null ? null : name.getNomenclaturalReference().getYear();
1088 //basionymAuthorship
1089 csvLine[table.getIndex(ColDpExportTable.NAME_BASIONYM_AUTHORSHIP)] = teamToString(name.getBasionymAuthorship());
1090 //basionymExAuthorship
1091 csvLine[table.getIndex(ColDpExportTable.NAME_BASIONYM_EX_AUTHORSHIP)] = teamToString(name.getExBasionymAuthorship());
1092 //basionymAuthorshipYear
1093 csvLine[table.getIndex(ColDpExportTable.NAME_BASIONYM_AUTHORSHIP_YEAR)] =
1094 basionym == null? null :
1095 basionym.getNomenclaturalReference() == null ? null :
1096 basionym.getNomenclaturalReference().getYear();
1097
1098 //rank
1099 csvLine[table.getIndex(ColDpExportTable.RANK)] = state.getTransformer().getCacheByRank(rank);
1100
1101 //uninomial / genus
1102 if (name.isGenusOrSupraGeneric()) {
1103 csvLine[table.getIndex(ColDpExportTable.NAME_UNINOMIAL)] = name.getGenusOrUninomial();
1104 }else {
1105 csvLine[table.getIndex(ColDpExportTable.NAME_GENUS)] = name.getGenusOrUninomial();
1106 }
1107
1108 csvLine[table.getIndex(ColDpExportTable.NAME_INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
1109 csvLine[table.getIndex(ColDpExportTable.NAME_SPECIFIC_EPITHET)] = name.getSpecificEpithet();
1110 csvLine[table.getIndex(ColDpExportTable.NAME_INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
1111
1112 //TODO 3 name cultivar epithet, group epithet
1113 csvLine[table.getIndex(ColDpExportTable.NAME_CULTIVAR_EPITHET)] = name.getCultivarEpithet();
1114
1115 //code
1116 csvLine[table.getIndex(ColDpExportTable.NAME_CODE)] = state.getTransformer().getCacheByNomenclaturalCode(name.getNameType());
1117
1118 //TODO 5 name status, is this handling correct?
1119 //Also according to documentation we should put more detailed status information to the remarks field
1120 // or an URI from the NOMEN ontology could be used
1121 if (name.getStatus() == null || name.getStatus().isEmpty()) {
1122 csvLine[table.getIndex(ColDpExportTable.NAME_STATUS)] = "acceptable";
1123 } else {
1124 NomenclaturalStatus status = name.getStatus().iterator().next();
1125 if (name.getStatus().size() > 1) {
1126 String message = "There is >1 name status for " + name.getTitleCache();
1127 state.getResult().addWarning(message);
1128 }
1129 String statusTypeString = state.getTransformer().getCacheByNomStatus(status.getType());
1130 csvLine[table.getIndex(ColDpExportTable.NAME_STATUS)] = statusTypeString;
1131 if (statusTypeString == null) {
1132 String message = "Name status " + status.getType() + " not yet handled for name " + name.getTitleCache();
1133 state.getResult().addWarning(message);
1134 }
1135 }
1136
1137 //nom. ref.
1138 Reference nomRef = name.getNomenclaturalReference();
1139 if (nomRef != null) {
1140 csvLine[table.getIndex(ColDpExportTable.REFERENCE_ID)] = getId(state, nomRef);
1141 handleReference(state, nomRef);
1142
1143 //publishedInYear
1144 if (nomRef.getDatePublished() != null) {
1145 csvLine[table.getIndex(ColDpExportTable.NAME_PUBLISHED_IN_YEAR)] = nomRef.getDatePublished().getYear();
1146 }
1147 nomRef = HibernateProxyHelper.deproxy(nomRef);
1148 if (nomRef.getInReference() != null) {
1149 Reference inReference = nomRef.getInReference();
1150 if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null) {
1151 csvLine[table.getIndex(ColDpExportTable.NAME_PUBLISHED_IN_YEAR)]
1152 = inReference.getDatePublished().getYear();
1153 }
1154 }
1155 }
1156
1157 //publishedInPage
1158 if (name.getNomenclaturalMicroReference() != null) {
1159 csvLine[table.getIndex(ColDpExportTable.NAME_PUBLISHED_IN_PAGE)] = name.getNomenclaturalMicroReference();
1160 }
1161
1162 //publishedInPageLink
1163 String protologueUriString = extractProtologueURIs(state, name);
1164 csvLine[table.getIndex(ColDpExportTable.NAME_PUBLISHED_IN_PAGE_LINK)] = protologueUriString;
1165
1166 //TODO 2 name links - do we have this in CDM?
1167
1168 //remarks
1169 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = getRemarks(name);
1170
1171 handleTypeMaterial(state, name);
1172
1173
1174 state.getProcessor().put(table, name, csvLine);
1175 //TODO 1 nameRelationships - is this still an open issue? Do tests exist?
1176 handleNameRelationships(state, name);
1177
1178 } catch (Exception e) {
1179 state.getResult().addException(e,
1180 "An unexpected error occurred when handling the name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1181
1182 e.printStackTrace();
1183 }
1184 }
1185
1186 private String teamToString(TeamOrPersonBase<?> author) {
1187 if (author == null) {
1188 return null;
1189 }
1190 String nomCache = author.getNomenclaturalTitleCache();
1191 if (StringUtils.isEmpty(nomCache)){
1192 return null;
1193 }else {
1194 return nomCache
1195 .replace(", ", "|")
1196 .replace(",", "|")
1197 .replace(" & ", "|")
1198 .replace("&", "|")
1199 .replace(" et ", "|");
1200 }
1201 }
1202
1203 private void handleTypeMaterial(ColDpExportState state, TaxonName name) {
1204 try {
1205 ColDpExportTable table = ColDpExportTable.TYPE_MATERIAL;
1206 String[] csvLine = new String[table.getSize()];
1207
1208 Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1209 List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1210
1211 for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1212 if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1213 if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1214 Set<IdentifiableSource> sources = typeDesignation.getSources();
1215 boolean isProtologue = false;
1216 if (sources != null && !sources.isEmpty()){
1217 IdentifiableSource source = sources.iterator().next();
1218 if (name.getNomenclaturalReference() != null){
1219 isProtologue = source.getCitation() != null? source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid()): false;
1220 }
1221 }
1222 if (isProtologue){
1223 csvLine[table.getIndex(ColDpExportTable.TYPE_CITATION)] = ((TextualTypeDesignation) typeDesignation)
1224 .getPreferredText(Language.DEFAULT());
1225 }else{
1226 //TODO 2 specimen type textual type designation, still open?
1227 textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1228 }
1229 } else {
1230 ///TODO 2 specimen type textual type designation, still open?
1231 textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1232 }
1233 } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1234 SpecimenTypeDesignation specimenType = HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class);
1235 specimenTypeDesignations.add(specimenType);
1236 handleSpecimenType(state, specimenType, csvLine, table, name);
1237 }else if (typeDesignation instanceof NameTypeDesignation){
1238 //ignore
1239 // specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
1240 }
1241 }
1242
1243 TypeDesignationSetContainer typeContainer = new TypeDesignationSetContainer(specimenTypeDesignations, name, TypeDesignationSetComparator.ORDER_BY.TYPE_STATUS);
1244 HTMLTagRules rules = new HTMLTagRules();
1245 //rules.addRule(TagEnum.name, "i");
1246 csvLine[table.getIndex(ColDpExportTable.TYPE_CITATION)] = typeContainer.print(false, false, false, rules);
1247
1248 //TODO 2 type material what is this second type computation? Is it only about sources?
1249 StringBuilder stringbuilder = new StringBuilder();
1250 int i = 1;
1251 for (TextualTypeDesignation typeDesignation : textualTypeDesignations) {
1252 stringbuilder.append(typeDesignation.getPreferredText(Language.DEFAULT()));
1253 if (typeDesignation.getSources() != null && !typeDesignation.getSources().isEmpty() ){
1254 stringbuilder.append( " [");
1255 int index = 1;
1256 for (IdentifiableSource source: typeDesignation.getSources()){
1257 if (source.getCitation() != null){
1258 stringbuilder.append(OriginalSourceFormatter.INSTANCE.format(source));
1259 }
1260 if (index < typeDesignation.getSources().size()) {
1261 stringbuilder.append( ", ");
1262 }
1263 index++;
1264 }
1265 stringbuilder.append( "]");
1266 }
1267 if (i < textualTypeDesignations.size()) {
1268 stringbuilder.append( "; ");
1269 } else {
1270 stringbuilder.append(".");
1271 }
1272 i++;
1273 }
1274 csvLine[table.getIndex(ColDpExportTable.TYPE_CITATION)] = stringbuilder.toString();
1275 } catch (Exception e) {
1276 state.getResult().addException(e,
1277 "An unexpected error occurred when handling the type designations for name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1278 e.printStackTrace();
1279 }
1280 }
1281
1282 //TODO 2 specimen type what is the difference to handleSpecimenType()
1283 // private void handleSpecimenType_(ColDpExportState state, SpecimenTypeDesignation specimenType) {
1284 //
1285 // if (specimenType.getTypeSpecimen() != null){
1286 // DerivedUnit specimen = specimenType.getTypeSpecimen();
1287 // if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1288 // handleSpecimen(state, specimen);
1289 // }
1290 // }
1291 //
1292 // String[] csvLine = new String[table.getSize()];
1293 // //TYPE_ID, SPECIMEN_FK, TYPE_VERBATIM_CITATION, TYPE_STATUS, TYPE_DESIGNATED_BY_STRING, TYPE_DESIGNATED_BY_REF_FK};
1294 // //Specimen_Fk und den Typusangaben (Art des Typus [holo, lecto, etc.], Quelle, Designation-Quelle, +
1295 // Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1296 // for (TaxonName name: typifiedNames){
1297 // csvLine[table.getIndex(ColDpExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1298 // csvLine[table.getIndex(ColDpExportTable.TYPE_ID)] = getId(state, specimenType);
1299 // csvLine[table.getIndex(ColDpExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1300 // csvLine[table.getIndex(ColDpExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1301 // if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1302 // String sourceString = "";
1303 // int index = 0;
1304 // for (IdentifiableSource source: specimenType.getSources()){
1305 // if (source.getCitation()!= null){
1306 // sourceString = sourceString.concat(source.getCitation().getCitation());
1307 // }
1308 // index++;
1309 // if (index != specimenType.getSources().size()){
1310 // sourceString.concat(", ");
1311 // }
1312 // }
1313 // csvLine[table.getIndex(ColDpExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1314 // }
1315 // if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1316 // handleReference(state, specimenType.getDesignationSource().getCitation());
1317 // csvLine[table.getIndex(ColDpExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1318 // }
1319 //
1320 // state.getProcessor().put(table, specimenType, csvLine);
1321 // }
1322 // }
1323
1324 private void handleSpecimenType(ColDpExportState state, SpecimenTypeDesignation specimenType, String[] csvLine, ColDpExportTable table, TaxonName name) {
1325
1326 try {
1327
1328 DerivedUnit specimen = specimenType.getTypeSpecimen();
1329 if (specimenType.getTypeSpecimen() == null){
1330 return;
1331 //handleSpecimen(state, specimen);
1332 }
1333
1334 //ID - TODO 3 specimen type best use dwc:occurrenceID
1335 csvLine[table.getIndex(ColDpExportTable.ID)] = getId(state, specimen);
1336
1337 //TODO 9 specimenType sourceID //handled in referenceID
1338 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
1339
1340 //nameID
1341 Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1342 if (typifiedNames.size() > 1){
1343 //TODO 3 specimen type we should
1344 state.getResult().addWarning("Please check the specimen type "
1345 + cdmBaseStr(specimenType) + " there are more then one typified name.");
1346 }
1347 // if (typifiedNames.iterator().hasNext()){
1348 // TaxonName name = typifiedNames.iterator().next();
1349 csvLine[table.getIndex(ColDpExportTable.TYPE_NAMEID)] = getId(state, name);
1350 // }
1351
1352 //TODO 3 specimen type citation - also done in calling method
1353 csvLine[table.getIndex(ColDpExportTable.TYPE_CITATION)] = specimen.getTitleCache();
1354
1355
1356 //TODO 3 specimen type type status transformation
1357 csvLine[table.getIndex(ColDpExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1358
1359 //TODO 2 specimen type referenceID - see description, should be designation ref id or original name refid
1360 if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1361 //TODO 3 specimen type, should be source, not reference; why?
1362 handleReference(state, specimenType.getDesignationSource().getCitation());
1363 csvLine[table.getIndex(ColDpExportTable.REFERENCE_ID)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1364 }
1365
1366 //institution code
1367 if (specimen.getCollection() != null) {
1368 //TODO 3 specimen type institution code not available handling
1369 csvLine[table.getIndex(ColDpExportTable.TYPE_INSTITUTION_CODE)] = specimen.getCollection().getCode();
1370 }
1371
1372 //catalog number
1373 if (specimen.isInstanceOf(DerivedUnit.class)){
1374 DerivedUnit derivedUnit = specimen;
1375 String catalogNumber = null;
1376 if (!StringUtils.isBlank(derivedUnit.getBarcode())){
1377 catalogNumber = derivedUnit.getBarcode();
1378 } else if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
1379 catalogNumber = derivedUnit.getAccessionNumber();
1380 } else if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
1381 catalogNumber = derivedUnit.getCatalogNumber();
1382 }
1383 csvLine[table.getIndex(ColDpExportTable.TYPE_CATALOG_NUMBER)] = catalogNumber;
1384 }
1385
1386 //TODO 9 specimen type associatedSequences - not yet implemented
1387 csvLine[table.getIndex(ColDpExportTable.TYPE_ASSOC_SEQ)] = null;
1388
1389 //sex
1390 if (specimen.getSex() != null) {
1391 //TODO 7 specimen type transform sex, we usually don't have specimen with sex
1392 csvLine[table.getIndex(ColDpExportTable.TYPE_SEX)] = specimen.getSex().getLabel();
1393 }
1394
1395 //link
1396 if (specimen.getPreferredStableUri() != null) {
1397 csvLine[table.getIndex(ColDpExportTable.LINK)] = specimen.getPreferredStableUri().toString();
1398 }
1399
1400 //remarks
1401 //TODO 3 specimen type gather remarks on type designation, field unit(s) and specimen
1402 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = getRemarks(specimen);
1403
1404 //field unit
1405 //TODO 3 specimen type performance due to service call
1406 Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
1407 if (!fieldUnits.isEmpty()) {
1408 if (fieldUnits.size() > 1) {
1409 state.getResult().addWarning("There are >1 field units for specimen "
1410 + cdmBaseStr(specimen) + ".");
1411 }
1412
1413 FieldUnit fieldUnit = fieldUnits.iterator().next();
1414
1415 GatheringEvent gathering = fieldUnit.getGatheringEvent();
1416 if (gathering != null) {
1417 handleGatheringEvent(state, csvLine, table, fieldUnit, gathering);
1418 }
1419 }
1420
1421 state.getProcessor().put(table, specimenType, csvLine);
1422 }catch (Exception e) {
1423 state.getResult().addException(e,
1424 "An unexpected error occurred when handling type material for name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1425 e.printStackTrace();
1426 }
1427 }
1428
1429 private void handleGatheringEvent(ColDpExportState state, String[] csvLine, ColDpExportTable table,
1430 FieldUnit fieldUnit, GatheringEvent gathering) {
1431 //locality
1432 if (gathering.getLocality() != null) {
1433 csvLine[table.getIndex(ColDpExportTable.TYPE_LOCALITY)]
1434 = gathering.getLocality().getText();
1435 }
1436 //TODO 3 gathering include areas, see CDM-light implementation and COL-DP description
1437
1438 //country
1439 if (gathering.getCountry() != null) {
1440 csvLine[table.getIndex(ColDpExportTable.TYPE_COUNTRY)]
1441 = gathering.getCountry().getLabel();
1442 }
1443
1444 //exact location
1445 Point point = gathering.getExactLocation();
1446 if (point != null) {
1447 //latitude
1448 if (point.getLatitude() != null) {
1449 //TODO 3 gathering rounding
1450 csvLine[table.getIndex(ColDpExportTable.TYPE_LATITUDE)]
1451 = point.getLatitude().toString();
1452 }
1453 //longitude
1454 if (point.getLongitude() != null) {
1455 //TODO 3 gathering rounding
1456 csvLine[table.getIndex(ColDpExportTable.TYPE_LONGITUDE)]
1457 = point.getLongitude().toString();
1458 }
1459 }
1460
1461 //altitude
1462 if (gathering.getAbsoluteElevation() != null) {
1463 //TODO 3 type specimen include max/text/depth
1464 csvLine[table.getIndex(ColDpExportTable.TYPE_ALTITUDE)]
1465 = gathering.getAbsoluteElevation().toString();
1466 }
1467
1468 //host - does more or less not exist in CDM
1469 csvLine[table.getIndex(ColDpExportTable.TYPE_HOST)] = null;
1470
1471 //date
1472 if (gathering.getGatheringDate() != null) {
1473 //TODO 3 specimen type ISO 8601
1474 csvLine[table.getIndex(ColDpExportTable.TYPE_DATE)] = gathering
1475 .getGatheringDate().toString();
1476 }
1477
1478
1479 csvLine[table.getIndex(ColDpExportTable.TYPE_COLLECTOR)]
1480 = createCollectorString(state, gathering, fieldUnit);
1481 //field number not yet in COL-DP
1482 //csvLine[table.getIndex(ColDpExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
1483 }
1484
1485 private String createNameWithItalics(List<TaggedText> taggedName) {
1486
1487 String fullTitleWithHtml = "";
1488 for (TaggedText taggedText: taggedName){
1489 if (taggedText.getType().equals(TagEnum.name)){
1490 fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1491 }else if (taggedText.getType().equals(TagEnum.separator)){
1492 fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1493 }else{
1494 fullTitleWithHtml += taggedText.getText() + " ";
1495 }
1496 }
1497 return fullTitleWithHtml;
1498 }
1499
1500 private void handleNameRelationships(ColDpExportState state, TaxonName name) {
1501 ColDpExportTable table = ColDpExportTable.NAME_RELATION;
1502 ColDpExportTransformer transformer = (ColDpExportTransformer)state.getTransformer();
1503 try {
1504 //relations in which "name" is the from name
1505 Set<NameRelationship> fromRels = name.getRelationsFromThisName();
1506 for (NameRelationship rel : fromRels) {
1507 ColDpNameRelType coldpType = transformer.getColDpNameRelTypeByNameRelationType(rel.getType());
1508 if (coldpType == null) {
1509 handleNoColDpNameRelType(state, rel.getType(), name);
1510 continue;
1511 }else if (coldpType.getDirection() == 0) {
1512 continue; //the relation is handled the other way round if necessary
1513 }
1514
1515 TaxonName name2 = CdmBase.deproxy(rel.getToName());
1516 handleRelNameCommonData(state, table, rel, name, name2, coldpType);
1517 }
1518
1519 //relations in which "name" is the toName
1520 Set<NameRelationship> toRels = name.getRelationsToThisName();
1521 for (NameRelationship rel : toRels) {
1522 ColDpNameRelType coldpType = transformer.getColDpNameRelTypeByNameRelationType(rel.getType());
1523 if (coldpType == null) {
1524 handleNoColDpNameRelType(state, rel.getType(), name);
1525 continue;
1526 }else if (coldpType.getDirection() == 1) {
1527 continue; //the relation is handled the other way round if necessary
1528 }
1529
1530 TaxonName name2 = CdmBase.deproxy(rel.getFromName());
1531 handleRelNameCommonData(state, table, rel, name, name2, coldpType);
1532 }
1533 } catch (Exception e) {
1534 state.getResult().addException(e,
1535 "An unexpected error occurred when handling name relationships for name "
1536 + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1537 e.printStackTrace();
1538 }
1539 }
1540
1541 private void handleNoColDpNameRelType(ColDpExportState state, NameRelationshipType nameRelType, TaxonName taxonName) {
1542 String warning;
1543 if (nameRelType == null) {
1544 warning = "Name relationship has not type for name " + taxonName.getTitleCache();
1545 } else {
1546 //TODO misspelling, alternative name, blocking name for, avoids homonym of, unspecific "non"
1547 warning = "Name relationship type not yet handled by COL-DP: " + nameRelType.getTitleCache() + "; name: " + taxonName.getTitleCache();
1548 }
1549 state.getResult().addWarning(warning);
1550 }
1551
1552 private void handleRelNameCommonData(ColDpExportState state, ColDpExportTable table,
1553 NameRelationship rel, TaxonName name, TaxonName relatedName, ColDpNameRelType coldpType) {
1554
1555 String[] csvLine = new String[table.getSize()];
1556
1557 if (!state.getNameStore().containsKey(relatedName.getId())) {
1558 handleName(state, relatedName, null);
1559 }
1560 csvLine[table.getIndex(ColDpExportTable.REL_NAME_NAMEID)] = getId(state, name);
1561 csvLine[table.getIndex(ColDpExportTable.REL_NAME_REL_NAMEID)] = getId(state, relatedName);
1562
1563 csvLine[table.getIndex(ColDpExportTable.TYPE)] = coldpType.getLabel();
1564 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
1565 if (rel.getCitation() != null) {
1566 handleReference(state, rel.getCitation());
1567 csvLine[table.getIndex(ColDpExportTable.REFERENCE_ID)] = getId(state, rel.getCitation());
1568 }
1569
1570 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = getRemarks(rel);
1571 state.getProcessor().put(table, rel.getUuid().toString(), csvLine);
1572 }
1573
1574 private String getVolume(Reference reference) {
1575 if (reference.getVolume() != null) {
1576 return reference.getVolume();
1577 } else if (reference.getInReference() != null) {
1578 if (reference.getInReference().getVolume() != null) {
1579 return reference.getInReference().getVolume();
1580 }
1581 }
1582 return null;
1583 }
1584
1585 // private void handleIdentifier(ColDpExportState state, CdmBase cdmBase) {
1586 // ColDpExportTable table = ColDpExportTable.IDENTIFIER;
1587 // String[] csvLine;
1588 // try {
1589 // if (cdmBase instanceof TaxonName){
1590 // TaxonName name = (TaxonName)cdmBase;
1591 //
1592 // try{
1593 // List<Identifier> identifiers = name.getIdentifiers();
1594 //
1595 // //first check which kind of identifiers are available and then sort and create table entries
1596 // Map<IdentifierType, Set<Identifier>> identifierTypes = new HashMap<>();
1597 // for (Identifier identifier: identifiers){
1598 // IdentifierType type = identifier.getType();
1599 // if (identifierTypes.containsKey(type)){
1600 // identifierTypes.get(type).add(identifier);
1601 // }else{
1602 // Set<Identifier> tempList = new HashSet<>();
1603 // tempList.add(identifier);
1604 // identifierTypes.put(type, tempList);
1605 // }
1606 // }
1607 //
1608 // for (IdentifierType type:identifierTypes.keySet()){
1609 // Set<Identifier> identifiersByType = identifierTypes.get(type);
1610 // csvLine = new String[table.getSize()];
1611 // csvLine[table.getIndex(ColDpExportTable.FK)] = getId(state, name);
1612 // csvLine[table.getIndex(ColDpExportTable.REF_TABLE)] = "ScientificName";
1613 // csvLine[table.getIndex(ColDpExportTable.IDENTIFIER_TYPE)] = type.getLabel();
1614 // csvLine[table.getIndex(ColDpExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1615 // identifiersByType);
1616 // state.getProcessor().put(table, name.getUuid() + ", " + type.getLabel(), csvLine);
1617 // }
1618 //
1619 //
1620 //// Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1621 //// Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1622 //// Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1623 //// if (!IPNIidentifiers.isEmpty()) {
1624 //// csvLine = new String[table.getSize()];
1625 //// csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1626 //// csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1627 //// csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1628 //// csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1629 //// IPNIidentifiers);
1630 //// state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1631 //// }
1632 //// if (!tropicosIdentifiers.isEmpty()) {
1633 //// csvLine = new String[table.getSize()];
1634 //// csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1635 //// csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1636 //// csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
1637 //// csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1638 //// tropicosIdentifiers);
1639 //// state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1640 //// }
1641 //// if (!WFOIdentifiers.isEmpty()) {
1642 //// csvLine = new String[table.getSize()];
1643 //// csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1644 //// csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1645 //// csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1646 //// csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1647 //// WFOIdentifiers);
1648 //// state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1649 //// }
1650 // }catch(Exception e){
1651 // state.getResult().addWarning("Please check the identifiers for "
1652 // + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1653 //
1654 //
1655 // }
1656 // }else{
1657 // if (cdmBase instanceof IdentifiableEntity){
1658 // IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1659 // List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1660 // String tableName = null;
1661 // if (cdmBase instanceof Reference){
1662 // tableName = "Reference";
1663 // }else if (cdmBase instanceof SpecimenOrObservationBase){
1664 // tableName = "Specimen";
1665 // }else if (cdmBase instanceof Taxon){
1666 // tableName = "Taxon";
1667 // }else if (cdmBase instanceof Synonym){
1668 // tableName = "Synonym";
1669 // }else if (cdmBase instanceof TeamOrPersonBase){
1670 // tableName = "PersonOrTeam";
1671 // }
1672 //
1673 // for (Identifier identifier: identifiers){
1674 // if (identifier.getType() == null && identifier.getIdentifier() == null){
1675 // state.getResult().addWarning("Please check the identifiers for "
1676 // + cdmBaseStr(cdmBase) + " there is an empty identifier");
1677 // continue;
1678 // }
1679 //
1680 // csvLine = new String[table.getSize()];
1681 // csvLine[table.getIndex(ColDpExportTable.FK)] = getId(state, cdmBase);
1682 //
1683 // if (tableName != null){
1684 // csvLine[table.getIndex(ColDpExportTable.REF_TABLE)] = tableName;
1685 // csvLine[table.getIndex(ColDpExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1686 // csvLine[table.getIndex(ColDpExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1687 // state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1688 // }
1689 // }
1690 // if (cdmBase instanceof Reference ){
1691 // Reference ref = (Reference)cdmBase;
1692 // if (ref.getDoi() != null){
1693 // csvLine = new String[table.getSize()];
1694 // csvLine[table.getIndex(ColDpExportTable.FK)] = getId(state, cdmBase);
1695 // csvLine[table.getIndex(ColDpExportTable.REF_TABLE)] = tableName;
1696 // csvLine[table.getIndex(ColDpExportTable.IDENTIFIER_TYPE)] = "DOI";
1697 // csvLine[table.getIndex(ColDpExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1698 // state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1699 // }
1700 // }
1701 //
1702 // if (cdmBase instanceof TeamOrPersonBase){
1703 // TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1704 // if (person instanceof Person && ((Person)person).getOrcid() != null){
1705 // csvLine = new String[table.getSize()];
1706 // csvLine[table.getIndex(ColDpExportTable.FK)] = getId(state, cdmBase);
1707 // csvLine[table.getIndex(ColDpExportTable.REF_TABLE)] = tableName;
1708 // csvLine[table.getIndex(ColDpExportTable.IDENTIFIER_TYPE)] = "ORCID";
1709 // csvLine[table.getIndex(ColDpExportTable.EXTERNAL_NAME_IDENTIFIER)]= ((Person)person).getOrcid().asURI();
1710 // state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1711 // }
1712 // }
1713 // }
1714 // }
1715 // } catch (Exception e) {
1716 // state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1717 // + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1718 // e.printStackTrace();
1719 // }
1720 // }
1721 //
1722 // private String extractIdentifier(Set<Identifier> identifierSet) {
1723 //
1724 // String identifierString = "";
1725 // for (Identifier identifier : identifierSet) {
1726 // if (!StringUtils.isBlank(identifierString)) {
1727 // identifierString += ", ";
1728 // }
1729 // identifierString += identifier.getIdentifier();
1730 // }
1731 // return identifierString;
1732 // }
1733
1734 private String extractProtologueURIs(ColDpExportState state, TaxonName name) {
1735 if (name.getNomenclaturalSource() != null){
1736 Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1737 return extractLinkUris(links.iterator());
1738 }else{
1739 return null;
1740 }
1741 }
1742
1743 private String extractMediaURIs(ColDpExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1744 Feature feature) {
1745
1746 String mediaUriString = "";
1747 Set<DescriptionElementBase> elements = new HashSet<>();
1748 for (DescriptionBase<?> description : descriptionsSet) {
1749 try {
1750 if (!description.getElements().isEmpty()) {
1751 elements = description.getElements();
1752
1753 for (DescriptionElementBase element : elements) {
1754 Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1755 if (entityFeature.equals(feature)) {
1756 if (!element.getMedia().isEmpty()) {
1757 List<Media> media = element.getMedia();
1758 for (Media mediaElement : media) {
1759 Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1760 mediaUriString = extractMediaUris(it);
1761 }
1762 }
1763 }
1764 }
1765 }
1766 } catch (Exception e) {
1767 state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1768 + cdmBaseStr(description) + ": " + e.getMessage());
1769 }
1770 }
1771 return mediaUriString;
1772 }
1773
1774
1775 private String extractStatusString(ColDpExportState state, TaxonName name, boolean abbrev) {
1776 try {
1777 Set<NomenclaturalStatus> status = name.getStatus();
1778 if (status.isEmpty()) {
1779 return "";
1780 }
1781 String statusString = "";
1782 for (NomenclaturalStatus nameStatus : status) {
1783 if (nameStatus != null) {
1784 if (abbrev) {
1785 if (nameStatus.getType() != null) {
1786 statusString += nameStatus.getType().getIdInVocabulary();
1787 }
1788 } else {
1789 if (nameStatus.getType() != null) {
1790 statusString += nameStatus.getType().getTitleCache();
1791 }
1792 }
1793 if (!abbrev) {
1794
1795 if (nameStatus.getRuleConsidered() != null
1796 && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1797 statusString += ": " + nameStatus.getRuleConsidered();
1798 }
1799 if (nameStatus.getCitation() != null) {
1800 String shortCitation = OriginalSourceFormatter.INSTANCE.format(nameStatus.getCitation(), null);
1801 statusString += " (" + shortCitation + ")";
1802 }
1803 // if (nameStatus.getCitationMicroReference() != null
1804 // && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1805 // statusString += " " + nameStatus.getCitationMicroReference();
1806 // }
1807 }
1808 statusString += " ";
1809 }
1810 }
1811 return statusString;
1812 } catch (Exception e) {
1813 state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1814 + cdmBaseStr(name) + ": " + e.getMessage());
1815 return "";
1816 }
1817 }
1818
1819 private void handleHomotypicalGroup(ColDpExportState state, HomotypicalGroup group, Taxon acceptedTaxon) {
1820 try {
1821
1822 List<TaxonName> typifiedNames = new ArrayList<>();
1823 if (acceptedTaxon != null){
1824 List<Synonym> synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group);
1825 if (group.equals(acceptedTaxon.getHomotypicGroup())){
1826 typifiedNames.add(acceptedTaxon.getName());
1827 }
1828 synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(CdmBase.deproxy(synonym.getName())));
1829 }
1830
1831
1832 TaxonName firstname = null;
1833 for (TaxonName name: typifiedNames){
1834 Iterator<Taxon> taxa = name.getTaxa().iterator();
1835 while(taxa.hasNext()){
1836 Taxon taxon = taxa.next();
1837 if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1838 firstname = name;
1839 break;
1840 }
1841 }
1842 }
1843
1844 //// Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1845 // String typifiedNamesString = "";
1846 // String typifiedNamesWithSecString = "";
1847 // String typifiedNamesWithoutAccepted = "";
1848 // String typifiedNamesWithoutAcceptedWithSec = "";
1849 // int index = 0;
1850 // for (TaxonName name : typifiedNames) {
1851 // // Concatenated output string for homotypic group (names and
1852 // // citations) + status + some name relations (e.g. “non”)
1853 // // TODO 3 commented code - can this be deleted? -- : nameRelations, which and how to display
1854 // Set<TaxonBase> taxonBases = name.getTaxonBases();
1855 // TaxonBase<?> taxonBase;
1856 //
1857 // String sec = "";
1858 // String nameString = name.getFullTitleCache();
1859 // String doubtful = "";
1860 //
1861 // if (state.getConfig().isAddHTML()){
1862 // nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1863 // }
1864 //
1865 // Set<NameRelationship> related = name.getNameRelations();
1866 // List<NameRelationship> relatedList = new ArrayList<>(related);
1867 //
1868 // Collections.sort(relatedList, (nr1, nr2)-> {
1869 // return nr1.getType().compareTo(nr2.getType());});
1870 //
1871 // List<NameRelationship> nonNames = new ArrayList<>();
1872 // List<NameRelationship> otherRelationships = new ArrayList<>();
1873 //
1874 // for (NameRelationship rel: relatedList){
1875 // //no inverse relations
1876 // if (rel.getFromName().equals(name)){
1877 // // alle Homonyme und inverse blocking names
1878 // if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1879 // || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1880 // || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1881 // || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
1882 // || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
1883 // ){
1884 // nonNames.add(rel);
1885 // }else if (!rel.getType().isBasionymRelation()){
1886 // otherRelationships.add(rel);
1887 // }
1888 // }
1889 // if (state.getConfig().isShowInverseNameRelationsInHomotypicGroup()) {
1890 // if (rel.getToName().equals(name)){
1891 // // alle Homonyme und inverse blocking names
1892 //// if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1893 //// || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1894 //// || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1895 //// || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
1896 //// || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
1897 //// ){
1898 //// nonNames.add(rel);
1899 //// }else if (!rel.getType().isBasionymRelation()){
1900 // otherRelationships.add(rel);
1901 //// }
1902 // }
1903 // }
1904 // }
1905 //
1906 // String nonRelNames = "";
1907 // String relNames = "";
1908 //
1909 // if (nonNames.size() > 0){
1910 // nonRelNames += " [";
1911 // }
1912 // for (NameRelationship relName: nonNames){
1913 // String label = "non ";
1914 // TaxonName relatedName = null;
1915 // if (relName.getFromName().equals(name)){
1916 // relatedName = relName.getToName();
1917 // if (state.getConfig().isAddHTML()){
1918 // nonRelNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
1919 // }else{
1920 // nonRelNames += label + relatedName.getTitleCache();
1921 // }
1922 // }
1923 //// else{
1924 //// label = relName.getType().getInverseLabel() + " ";
1925 //// relatedName = relName.getFromName();
1926 //// nonRelNames += label + relatedName.getTitleCache() + " ";
1927 //// }
1928 // }
1929 // nonRelNames.trim();
1930 // if (nonNames.size() > 0){
1931 // nonRelNames = StringUtils.strip(nonRelNames, null);
1932 // nonRelNames += "] ";
1933 // }
1934 //
1935 // //other relationships
1936 // if (otherRelationships.size() > 0){
1937 // relNames += " [";
1938 // }
1939 // for (NameRelationship rel: otherRelationships){
1940 // String label = "";
1941 // TaxonName relatedName = null;
1942 // if (rel.getFromName().equals(name)){
1943 // label = rel.getType().getLabel() + " ";
1944 // relatedName = rel.getToName();
1945 // if (state.getConfig().isAddHTML()){
1946 // relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
1947 // }else{
1948 // relNames += label + relatedName.getTitleCache();
1949 // }
1950 // }
1951 // else {
1952 // label = rel.getType().getInverseLabel() + " ";
1953 // relatedName = rel.getFromName();
1954 // if (state.getConfig().isAddHTML()){
1955 // relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
1956 // }else{
1957 // relNames += label + relatedName.getTitleCache();
1958 // }
1959 // }
1960 // }
1961 // relNames.trim();
1962 // if (otherRelationships.size() > 0){
1963 // relNames = StringUtils.stripEnd(relNames, null);
1964 // relNames += "] ";
1965 // }
1966 //
1967 //
1968 // String synonymSign = "";
1969 // if (index > 0){
1970 // if (name.isInvalid()){
1971 // synonymSign = "\u2212 ";
1972 // }else{
1973 // synonymSign = "\u2261 ";
1974 // }
1975 // }else{
1976 // if (name.isInvalid() ){
1977 // synonymSign = "\u2212 ";
1978 // }else{
1979 // synonymSign = "\u003D ";
1980 // }
1981 // }
1982 // boolean isAccepted = false;
1983 //
1984 // if (taxonBases.size() == 1){
1985 // taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
1986 //
1987 // if (taxonBase.getSec() != null){
1988 // sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(taxonBase.getSecSource());
1989 // }
1990 // if (taxonBase.isDoubtful()){
1991 // doubtful = "?";
1992 // }else{
1993 // doubtful = "";
1994 // }
1995 // if (taxonBase instanceof Synonym){
1996 // if (isNotBlank(sec)){
1997 // sec = " syn. sec. " + sec + " ";
1998 // }else {
1999 // sec = "";
2000 // }
2001 //
2002 // typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + nonRelNames + relNames;
2003 // typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2004 // }else{
2005 //// sec = "";
2006 // if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
2007 // isAccepted = true;
2008 // }else {
2009 // synonymSign = "\u003D ";
2010 // }
2011 //
2012 // }
2013 // if (taxonBase.getAppendedPhrase() != null){
2014 // if (state.getConfig().isAddHTML()){
2015 // String taxonString = createNameWithItalics(taxonBase.getTaggedTitle()) ;
2016 // taxonString = taxonString.replace("sec "+sec, "");
2017 // String nameCacheWithItalics = createNameWithItalics(name.getTaggedName());
2018 // nameString = nameString.replace(nameCacheWithItalics, taxonString);
2019 // }
2020 // }
2021 // }else{
2022 // //there are names used more than once?
2023 // for (TaxonBase<?> tb: taxonBases){
2024 // if (tb.getSec() != null){
2025 // sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(tb.getSecSource());
2026 // }
2027 // if (tb.isDoubtful()){
2028 // doubtful = "?";
2029 // }else{
2030 // doubtful = "";
2031 // }
2032 // if (tb instanceof Synonym ){
2033 // if (!((Synonym)tb).getAcceptedTaxon().equals(acceptedTaxon)) {
2034 // continue;
2035 // }
2036 // if (StringUtils.isNotBlank(sec)){
2037 // sec = " syn. sec. " + sec + " ";
2038 // }else {
2039 // sec = "";
2040 // }
2041 //
2042 // break;
2043 // }else{
2044 // sec = "";
2045 // if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
2046 // isAccepted = true;
2047 // break;
2048 // }else {
2049 // synonymSign = "\u003D ";
2050 // }
2051 // }
2052 // }
2053 // if (!isAccepted){
2054 // typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + "; ";
2055 // typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec;
2056 // typifiedNamesWithoutAcceptedWithSec = typifiedNamesWithoutAcceptedWithSec.trim() + "; ";
2057 // }
2058 // }
2059 // typifiedNamesString += synonymSign + doubtful + nameString + nonRelNames + relNames;
2060 // typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2061 //
2062 //
2063 // index++;
2064 // }
2065
2066 // state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
2067 } catch (Exception e) {
2068 state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
2069 + cdmBaseStr(group) + ": " + e.getMessage());
2070 }
2071 }
2072
2073 private void handleReference(ColDpExportState state, String[] csvLine, ColDpExportTable table,
2074 ISourceable<?> sourceable) {
2075
2076 String referenceID = null;
2077 for (IOriginalSource osb : sourceable.getSources()) {
2078 if (osb.getCitation() != null && osb.getType().isPrimarySource()) {
2079 referenceID = CdmUtils.concat(";", getId(state, osb.getCitation()));
2080 handleReference(state, osb.getCitation());
2081 }
2082 }
2083 csvLine[table.getIndex(ColDpExportTable.REFERENCE_ID)] = referenceID;
2084 }
2085
2086 private void handleReference(ColDpExportState state, Reference reference) {
2087 try {
2088 if (state.getReferenceStore().contains(reference.getUuid())) {
2089 return;
2090 }
2091
2092 state.addReferenceToStore(reference);
2093 ColDpExportTable table = ColDpExportTable.REFERENCE;
2094 String[] csvLine = new String[table.getSize()];
2095 reference = HibernateProxyHelper.deproxy(reference);
2096
2097 // TODO 1 reference short citations correctly
2098 // String shortCitation = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(reference, null); // Should be Author(year) like in Taxon.sec
2099 // csvLine[table.getIndex(ColDpExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
2100
2101 csvLine[table.getIndex(ColDpExportTable.ID)] = getId(state, reference);
2102
2103 //alternativeID
2104 handleAlternativeId(state, csvLine, table, reference);
2105
2106 //TODO 9 reference sourceID
2107 csvLine[table.getIndex(ColDpExportTable.SOURCE_ID)] = null;
2108
2109 //citation
2110 csvLine[table.getIndex(ColDpExportTable.REF_CITATION)] = reference.getCitation();
2111
2112 //type
2113 csvLine[table.getIndex(ColDpExportTable.TYPE)] = state.getTransformer().getCacheByReferenceType(reference);
2114
2115 //author
2116 if (reference.getAuthorship() != null) {
2117 TeamOrPersonBase<?> author = reference.getAuthorship();
2118 //TODO 3 reference author formatting fine tuning
2119 csvLine[table.getIndex(ColDpExportTable.REF_AUTHOR)] = author.getTitleCache();
2120 }
2121
2122 //editor
2123 if (reference.getEditor() != null) { //if in future this is not a String
2124 //TODO 3 reference editor formatting fine tuning, not yet relevant
2125 csvLine[table.getIndex(ColDpExportTable.REF_AUTHOR)] = reference.getEditor();
2126 }
2127
2128 // TODO 1 reference get preferred title
2129 csvLine[table.getIndex(ColDpExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
2130 ? reference.getTitleCache() : reference.getTitle();
2131 // csvLine[table.getIndex(ColDpExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
2132 // ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
2133
2134 //inRef
2135 if (reference.getInReference() != null && reference.getInSeries() != reference.getInReference()) {
2136 //TODO 2 reference exclude series as inRef
2137 Reference inRef = reference.getInReference();
2138
2139 //containerAuthor
2140 if (inRef.getAuthorship() != null) {
2141 TeamOrPersonBase<?> containerAuthor = inRef.getAuthorship();
2142 //TODO 1 reference inRef-author formatting fine tuning
2143 csvLine[table.getIndex(ColDpExportTable.REF_CONTAINER_AUTHOR)] = containerAuthor.getTitleCache();
2144 }
2145
2146 // TODO 1 reference get preferred inRef-title
2147 csvLine[table.getIndex(ColDpExportTable.REF_CONTAINER_TITLE)] = inRef.isProtectedTitleCache()
2148 ? inRef.getTitleCache() : inRef.getTitle();
2149 // csvLine[table.getIndex(ColDpExportTable.ABBREV_REF_TITLE)] = inRef.isProtectedAbbrevTitleCache()
2150 // ? inRef.getAbbrevTitleCache() : inRef.getAbbrevTitle();
2151
2152 }
2153
2154 //issued TODO 2 reference issued formatting
2155 csvLine[table.getIndex(ColDpExportTable.REF_ISSUED)] = reference.getDatePublishedString();
2156
2157 //accessed TODO 2 reference accessed also for source and formatting
2158 if (reference.getAccessed() != null) {
2159 csvLine[table.getIndex(ColDpExportTable.REF_ACCESSED)] = reference.getAccessed().toDate().toString();
2160 }
2161
2162 if (reference.getInSeries() != null) {
2163 Reference series = reference.getInReference();
2164
2165 //containerEditor
2166 if (series.getEditor() != null) {
2167 // TeamOrPersonBase<?> containerAuthor = series.getAuthorship();
2168 //TODO 2 reference collection editor
2169 csvLine[table.getIndex(ColDpExportTable.REF_COLLECTION_EDITOR)] = series.getEditor();
2170 }
2171
2172 // TODO 2 reference get preferred title
2173 //collection title
2174 csvLine[table.getIndex(ColDpExportTable.REF_COLLECTION_TITLE)] = series.isProtectedTitleCache()
2175 ? series.getTitleCache() : series.getTitle();
2176 // csvLine[table.getIndex(ColDpExportTable.ABBREV_REF_TITLE)] = inRef.isProtectedAbbrevTitleCache()
2177 // ? inRef.getAbbrevTitleCache() : inRef.getAbbrevTitle();
2178
2179 }
2180
2181 //volume
2182 csvLine[table.getIndex(ColDpExportTable.REF_VOLUME)] = getVolume(reference);
2183
2184 //issue TODO 2 reference issue (we currently do not handle issues separately, but could be parsed in some cases
2185 csvLine[table.getIndex(ColDpExportTable.REF_ISSUE)] = null;
2186
2187 //edition
2188 csvLine[table.getIndex(ColDpExportTable.REF_EDITION)] = reference.getEdition();
2189
2190 //volume
2191 csvLine[table.getIndex(ColDpExportTable.REF_PAGE)] = reference.getPages();
2192
2193 //publisher TODO 3 reference publisher2
2194 csvLine[table.getIndex(ColDpExportTable.REF_PUBLISHER)] = reference.getPublisher();
2195
2196 //publisherPlace TODO 3 reference publisherPlace2
2197 csvLine[table.getIndex(ColDpExportTable.REF_PUBLISHER_PLACE)] = reference.getPlacePublished();
2198
2199 //TODO 7 reference version does not exist yet in CDM
2200 csvLine[table.getIndex(ColDpExportTable.REF_VERSION)] = null; //reference.getVersion();
2201
2202 //isbn
2203 csvLine[table.getIndex(ColDpExportTable.REF_ISBN)] = reference.getIsbn();
2204
2205 //issn
2206 csvLine[table.getIndex(ColDpExportTable.REF_ISSN)] = reference.getIssn();
2207
2208 //doi
2209 csvLine[table.getIndex(ColDpExportTable.REF_DOI)] = reference.getDoiString();
2210
2211 //TODO 2 reference link link (=> external link)
2212 // csvLine[table.getIndex(ColDpExportTable.LINK)] = null;
2213 if (reference.getUri() != null) {
2214 csvLine[table.getIndex(ColDpExportTable.LINK)] = reference.getUri().toString();
2215 }
2216
2217 csvLine[table.getIndex(ColDpExportTable.REMARKS)] = getRemarks(reference);
2218
2219 state.getProcessor().put(table, reference, csvLine);
2220 } catch (Exception e) {
2221 e.printStackTrace();
2222 state.getResult().addException(e, "An unexpected error occurred when handling reference "
2223 + cdmBaseStr(reference) + ": " + e.getMessage());
2224 }
2225 }
2226
2227 //TODO 2 fullAuthorship - still needed?
2228 private String createFullAuthorship(Reference reference) {
2229 TeamOrPersonBase<?> authorship = reference.getAuthorship();
2230 String fullAuthorship = "";
2231 if (authorship == null) {
2232 return null;
2233 }
2234 authorship = HibernateProxyHelper.deproxy(authorship);
2235 if (authorship instanceof Person) {
2236 fullAuthorship = ((Person) authorship).getTitleCache();
2237
2238 } else if (authorship instanceof Team) {
2239
2240 Team authorTeam = (Team)authorship;
2241 fullAuthorship = authorTeam.cacheStrategy().getTitleCache(authorTeam);
2242 }
2243 return fullAuthorship;
2244 }
2245
2246 private String extractMediaUris(Iterator<MediaRepresentation> it) {
2247
2248 String mediaUriString = "";
2249 boolean first = true;
2250 while (it.hasNext()) {
2251 MediaRepresentation rep = it.next();
2252 List<MediaRepresentationPart> parts = rep.getParts();
2253 for (MediaRepresentationPart part : parts) {
2254 if (first) {
2255 if (part.getUri() != null) {
2256 mediaUriString += part.getUri().toString();
2257 first = false;
2258 }
2259 } else {
2260 if (part.getUri() != null) {
2261 mediaUriString += ", " + part.getUri().toString();
2262 }
2263 }
2264 }
2265 }
2266
2267 return mediaUriString;
2268 }
2269
2270 private String extractLinkUris(Iterator<ExternalLink> it) {
2271
2272 String linkUriString = "";
2273 boolean first = true;
2274 while (it.hasNext()) {
2275 ExternalLink link = it.next();
2276 if (first) {
2277 if (link.getUri() != null) {
2278 linkUriString += link.getUri().toString();
2279 first = false;
2280 }
2281 } else {
2282 if (link.getUri() != null) {
2283 linkUriString += ", " + link.getUri().toString();
2284 }
2285 }
2286 }
2287 return linkUriString;
2288 }
2289
2290 private String createCollectorString(ColDpExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2291 try {
2292 String collectorString = "";
2293 AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2294 if (gathering.getCollector() != null) {
2295 if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2296
2297 Person primaryCollector = fieldUnit.getPrimaryCollector();
2298 if (collectorA instanceof Team) {
2299 Team collectorTeam = (Team) collectorA;
2300 boolean isFirst = true;
2301 for (Person member : collectorTeam.getTeamMembers()) {
2302 if (!isFirst) {
2303 collectorString += "; ";
2304 }
2305 if (member.equals(primaryCollector)) {
2306 // highlight
2307 collectorString += "<b>" + member.getTitleCache() + "</b>";
2308 } else {
2309 collectorString += member.getTitleCache();
2310 }
2311 }
2312 }
2313 } else {
2314 collectorString = collectorA.getTitleCache();
2315 }
2316 }
2317 return collectorString;
2318 } catch (Exception e) {
2319 state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2320 + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2321 return "";
2322 }
2323 }
2324
2325
2326 /**
2327 * Returns a string representation of the {@link CdmBase cdmBase} object for
2328 * result messages.
2329 */
2330 private String cdmBaseStr(CdmBase cdmBase) {
2331 if (cdmBase == null) {
2332 return "-no object available-";
2333 } else {
2334 return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2335 }
2336 }
2337
2338 @Override
2339 protected boolean doCheck(ColDpExportState state) {
2340 return false;
2341 }
2342
2343 @Override
2344 protected boolean isIgnore(ColDpExportState state) {
2345 return false;
2346 }
2347 }