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