c5fa4fc09ecba73492d94fa97cccf7b726a86264
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / cdmLight / CdmLightClassificationExport.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.cdmLight;
10
11 import java.io.File;
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.Collections;
15 import java.util.Comparator;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22 import java.util.UUID;
23
24 import org.apache.commons.lang3.StringUtils;
25 import org.springframework.beans.factory.annotation.Autowired;
26 import org.springframework.stereotype.Component;
27
28 import eu.etaxonomy.cdm.api.service.geo.IDistributionService;
29 import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetComparator;
30 import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetContainer;
31 import eu.etaxonomy.cdm.api.service.name.TypeDesignationSetFormatter;
32 import eu.etaxonomy.cdm.common.CdmUtils;
33 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
34 import eu.etaxonomy.cdm.compare.name.TypeComparator;
35 import eu.etaxonomy.cdm.compare.taxon.HomotypicGroupTaxonComparator;
36 import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
37 import eu.etaxonomy.cdm.format.description.CategoricalDataFormatter;
38 import eu.etaxonomy.cdm.format.description.QuantitativeDataFormatter;
39 import eu.etaxonomy.cdm.format.description.distribution.CondensedDistribution;
40 import eu.etaxonomy.cdm.format.reference.OriginalSourceFormatter;
41 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
42 import eu.etaxonomy.cdm.io.common.CdmExportBase;
43 import eu.etaxonomy.cdm.io.common.ExportResult.ExportResultState;
44 import eu.etaxonomy.cdm.io.common.TaxonNodeOutStreamPartitioner;
45 import eu.etaxonomy.cdm.io.common.XmlExportState;
46 import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
47 import eu.etaxonomy.cdm.model.agent.AgentBase;
48 import eu.etaxonomy.cdm.model.agent.Person;
49 import eu.etaxonomy.cdm.model.agent.Team;
50 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
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.description.CategoricalData;
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.DescriptionElementSource;
66 import eu.etaxonomy.cdm.model.description.Distribution;
67 import eu.etaxonomy.cdm.model.description.Feature;
68 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
69 import eu.etaxonomy.cdm.model.description.QuantitativeData;
70 import eu.etaxonomy.cdm.model.description.TaxonDescription;
71 import eu.etaxonomy.cdm.model.description.TaxonInteraction;
72 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
73 import eu.etaxonomy.cdm.model.description.TextData;
74 import eu.etaxonomy.cdm.model.location.NamedArea;
75 import eu.etaxonomy.cdm.model.media.ExternalLink;
76 import eu.etaxonomy.cdm.model.media.Media;
77 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
78 import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
79 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
80 import eu.etaxonomy.cdm.model.name.NameRelationship;
81 import eu.etaxonomy.cdm.model.name.NameRelationshipType;
82 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
83 import eu.etaxonomy.cdm.model.name.NomenclaturalSource;
84 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
85 import eu.etaxonomy.cdm.model.name.Rank;
86 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
87 import eu.etaxonomy.cdm.model.name.TaxonName;
88 import eu.etaxonomy.cdm.model.name.TextualTypeDesignation;
89 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
90 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
91 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
92 import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
93 import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
94 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
95 import eu.etaxonomy.cdm.model.reference.NamedSource;
96 import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
97 import eu.etaxonomy.cdm.model.reference.Reference;
98 import eu.etaxonomy.cdm.model.reference.ReferenceType;
99 import eu.etaxonomy.cdm.model.taxon.Classification;
100 import eu.etaxonomy.cdm.model.taxon.Synonym;
101 import eu.etaxonomy.cdm.model.taxon.Taxon;
102 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
103 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
104 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
105 import eu.etaxonomy.cdm.model.term.IdentifierType;
106 import eu.etaxonomy.cdm.model.term.TermTree;
107 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDto;
108 import eu.etaxonomy.cdm.persistence.dto.TaxonNodeDtoByRankAndNameComparator;
109 import eu.etaxonomy.cdm.strategy.cache.HTMLTagRules;
110 import eu.etaxonomy.cdm.strategy.cache.TagEnum;
111 import eu.etaxonomy.cdm.strategy.cache.TaggedText;
112 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
113
114 /**
115 * The export exporting a classification or a taxonomic subtree into CDM light.
116 *
117 * @author k.luther
118 * @since 15.03.2017
119 */
120 @Component
121 public class CdmLightClassificationExport
122 extends CdmExportBase<CdmLightExportConfigurator, CdmLightExportState, IExportTransformer, File>{
123
124 private static final long serialVersionUID = 2518643632756927053L;
125
126 @Autowired
127 private IDistributionService distributionService;
128
129 public CdmLightClassificationExport() {
130 this.ioName = this.getClass().getSimpleName();
131 }
132
133 @Override
134 public long countSteps(CdmLightExportState state) {
135 TaxonNodeFilter filter = state.getConfig().getTaxonNodeFilter();
136 return getTaxonNodeService().count(filter);
137 }
138
139 @Override
140 protected void doInvoke(CdmLightExportState state) {
141 try {
142
143 IProgressMonitor monitor = state.getConfig().getProgressMonitor();
144 CdmLightExportConfigurator config = state.getConfig();
145 if (config.getTaxonNodeFilter().hasClassificationFilter()) {
146 Classification classification = getClassificationService()
147 .load(config.getTaxonNodeFilter().getClassificationFilter().get(0).getUuid());
148 state.setRootId(classification.getRootNode().getUuid());
149
150 } else if (config.getTaxonNodeFilter().hasSubtreeFilter()) {
151 state.setRootId(config.getTaxonNodeFilter().getSubtreeFilter().get(0).getUuid());
152 }
153 @SuppressWarnings("unchecked")
154 TaxonNodeOutStreamPartitioner<XmlExportState> partitioner = TaxonNodeOutStreamPartitioner.NewInstance(this,
155 state, state.getConfig().getTaxonNodeFilter(), 100, monitor, null);
156
157 handleMetaData(state);
158 monitor.subTask("Start partitioning");
159
160 TaxonNode node = partitioner.next();
161 while (node != null) {
162 handleTaxonNode(state, node);
163 node = partitioner.next();
164 }
165 // get rootNode and create helperObjects
166 if (state.getRootId() != null) {
167 List<TaxonNodeDto> childrenOfRoot = state.getNodeChildrenMap().get(state.getRootId());
168
169 Comparator<TaxonNodeDto> comp = state.getConfig().getTaxonNodeComparator();
170 if (comp == null) {
171 comp = new TaxonNodeDtoByRankAndNameComparator();
172 }
173 if (childrenOfRoot != null) {
174 Collections.sort(childrenOfRoot, comp);
175 OrderHelper helper = new OrderHelper(state.getRootId());
176 helper.setOrderIndex(state.getActualOrderIndexAndUpdate());
177 state.getOrderHelperMap().put(state.getRootId(), helper);
178
179 for (TaxonNodeDto child : childrenOfRoot) {
180 OrderHelper childHelper = new OrderHelper(child.getTaxonUuid());
181 helper.addChild(childHelper);
182 childHelper.setOrderIndex(state.getActualOrderIndexAndUpdate());
183 childHelper.addChildren(
184 createOrderHelper(state.getNodeChildrenMap().get(child.getUuid()), state));
185 }
186 }
187
188 state.getNodeChildrenMap().clear();
189 for (OrderHelper order : state.getOrderHelperMap().values()) {
190 setOrderIndex(state, order);
191 }
192 }
193
194 state.getProcessor().createFinalResult(state);
195 } catch (Exception e) {
196 state.getResult().addException(e,
197 "An unexpected error occurred in main method doInvoke() " + e.getMessage());
198 e.printStackTrace();
199 }
200 }
201
202 private void setOrderIndex(CdmLightExportState state, OrderHelper order) {
203
204 if (order.getTaxonUuid() != null
205 && state.getProcessor().hasRecord(CdmLightExportTable.TAXON, order.getTaxonUuid().toString())) {
206 String[] csvLine = state.getProcessor().getRecord(CdmLightExportTable.TAXON,
207 order.getTaxonUuid().toString());
208 csvLine[CdmLightExportTable.TAXON.getIndex(CdmLightExportTable.SORT_INDEX)] = String
209 .valueOf(order.getOrderIndex());
210 }
211
212 if (order.getChildren() == null) {
213 return;
214 }
215 for (OrderHelper helper : order.getChildren()) {
216 setOrderIndex(state, helper);
217 }
218 }
219
220 private List<OrderHelper> createOrderHelper(List<TaxonNodeDto> nodes, CdmLightExportState state) {
221 List<TaxonNodeDto> children = nodes;
222 // alreadySortedNodes.add(parentUuid);
223 if (children == null) {
224 return null;
225 }
226 Comparator<TaxonNodeDto> comp = state.getConfig().getTaxonNodeComparator();
227 if (comp == null) {
228 comp = new TaxonNodeDtoByRankAndNameComparator();
229 }
230 Collections.sort(children, comp);
231 // TODO: nochmal checken!!!
232 OrderHelper helperChild;
233 List<OrderHelper> childrenHelper = new ArrayList<>();
234 for (TaxonNodeDto child : children) {
235 helperChild = new OrderHelper(child.getTaxonUuid());
236 helperChild.setOrderIndex(state.getActualOrderIndexAndUpdate());
237
238 if (state.getNodeChildrenMap().get(child.getUuid()) != null) {
239 children = state.getNodeChildrenMap().get(child.getUuid());
240 helperChild.addChildren(createOrderHelper(children, state));
241 }
242 childrenHelper.add(helperChild);
243 }
244 return childrenHelper;
245 }
246
247 private void handleTaxonNode(CdmLightExportState state, TaxonNode taxonNode) {
248
249 if (taxonNode == null) {
250 String message = "TaxonNode for given taxon node UUID not found. ";
251 // TODO
252 state.getResult().addWarning(message);
253 } else {
254 try {
255 TaxonNode root = taxonNode;
256 List<TaxonNodeDto> childNodes;
257 if (root.hasChildNodes()) {
258 childNodes = new ArrayList<>();
259 for (TaxonNode child : root.getChildNodes()) {
260 if (child != null) {
261 childNodes.add(new TaxonNodeDto(child));
262 }
263 }
264 state.getNodeChildrenMap().put(root.getUuid(), childNodes);
265
266 // add root to node map
267 }
268 TaxonNodeDto rootDto = new TaxonNodeDto(root);
269 UUID parentUuid = root.getParent() != null ? root.getParent().getUuid()
270 : state.getClassificationUUID(root);
271 List<TaxonNodeDto> children = state.getNodeChildrenMap().get(parentUuid);
272 if (children != null && !children.contains(rootDto)) {
273 state.getNodeChildrenMap().get(parentUuid).add(rootDto);
274 } else if (state.getNodeChildrenMap().get(parentUuid) == null) {
275 List<TaxonNodeDto> rootList = new ArrayList<>();
276 rootList.add(rootDto);
277 state.getNodeChildrenMap().put(parentUuid, rootList);
278 }
279 if (root.hasTaxon()) {
280 handleTaxon(state, root);
281 }
282 } catch (Exception e) {
283 state.getResult().addException(e, "An unexpected error occurred when handling taxonNode "
284 + taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
285 }
286 }
287 }
288
289 private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
290 try {
291
292 if (taxonNode == null) {
293 state.getResult().addError("The taxonNode was null.", "handleTaxon");
294 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
295 return;
296 }
297 if (taxonNode.getTaxon() == null) {
298 state.getResult().addError("There was a taxon node without a taxon: " + taxonNode.getUuid(),
299 "handleTaxon");
300 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
301 } else {
302 Taxon taxon = CdmBase.deproxy(taxonNode.getTaxon());
303
304 try {
305 //accepted name
306 TaxonName name = taxon.getName();
307 handleName(state, name, taxon, true);
308
309 //homotypic group / synonyms
310 HomotypicalGroup homotypicGroup = taxon.getHomotypicGroup();
311 int index = 0;
312 int homotypicGroupIndex = 0;
313 handleHomotypicalGroup(state, homotypicGroup, taxon, homotypicGroupIndex);
314 homotypicGroupIndex++;
315 for (Synonym syn : taxon.getSynonymsInGroup(homotypicGroup)) {
316 handleSynonym(state, syn, index);
317 index++;
318 }
319 List<HomotypicalGroup> heterotypicHomotypicGroups = taxon.getHeterotypicSynonymyGroups();
320 for (HomotypicalGroup group: heterotypicHomotypicGroups){
321 handleHomotypicalGroup(state, group, taxon, homotypicGroupIndex);
322 for (Synonym syn : taxon.getSynonymsInGroup(group)) {
323 handleSynonym(state, syn, index);
324 index++;
325 }
326 homotypicGroupIndex++;
327 }
328
329 //pro parte synonyms
330 index = 0;
331 for (Taxon tax : taxon.getAllProParteSynonyms()) {
332 handleProPartePartialMisapplied(state, tax, taxon, true, false, index);
333 index++;
334 }
335
336 //misapplications
337 for (Taxon tax : taxon.getAllMisappliedNames()) {
338 handleProPartePartialMisapplied(state, tax, taxon, false, true, index);
339 index++;
340 }
341
342 //taxon table
343 CdmLightExportTable table = CdmLightExportTable.TAXON;
344 String[] csvLine = new String[table.getSize()];
345
346 csvLine[table.getIndex(CdmLightExportTable.TAXON_ID)] = getId(state, taxon);
347 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
348 Taxon parent = (taxonNode.getParent() == null) ? null : taxonNode.getParent().getTaxon();
349 csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
350
351 //secundum reference
352 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
353 if (taxon.getSec() != null && taxon.getSec().getDatePublished() != null
354 && taxon.getSec().getDatePublished().getFreeText() != null) {
355 String sec_string = taxon.getSec().getTitleCache() + ". "
356 + taxon.getSec().getDatePublished().getFreeText();
357 sec_string = sec_string.replace("..", ".");
358 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = sec_string;
359 } else {
360 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(taxon.getSec());
361 }
362 if (taxon.getSec() != null) {
363 if (!state.getReferenceStore().contains((taxon.getSec().getUuid()))) {
364 handleReference(state, taxon.getSec());
365 }
366 }
367 //secundum subname
368 TaxonName subName = taxon.getSecSource() == null? null : taxon.getSecSource().getNameUsedInSource();
369 if (subName != null) {
370 csvLine[table.getIndex(CdmLightExportTable.SEC_SUBNAME_FK)] = getId(state, subName);
371 if (!state.getNameStore().containsKey((subName.getId()))) {
372 handleName(state, subName, null);
373 }
374 csvLine[table.getIndex(CdmLightExportTable.SEC_SUBNAME)] = subName.getNameCache();
375 csvLine[table.getIndex(CdmLightExportTable.SEC_SUBNAME_AUTHORS)] = subName.getAuthorshipCache();
376 }
377
378 csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = taxon.getAppendedPhrase();
379 csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state,
380 taxonNode.getClassification());
381 csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification()
382 .getTitleCache();
383 csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = taxon.isPublish() ? "1" : "0";
384
385 //taxon node
386 csvLine[table.getIndex(CdmLightExportTable.INCLUDED)] = taxonNode.getStatus() == null ? "1" : "0";
387 csvLine[table.getIndex(CdmLightExportTable.DOUBTFUL)] = taxonNode.isDoubtful() ? "1" : "0";
388 csvLine[table.getIndex(CdmLightExportTable.UNPLACED)] = taxonNode.isUnplaced() ? "1" : "0";
389 csvLine[table.getIndex(CdmLightExportTable.EXCLUDED)] = taxonNode.isExcluded() ? "1" : "0";
390 csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_EXACT)] = taxonNode.isExcludedExact() ? "1" : "0";
391 csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_GEO)] = taxonNode.isGeographicallyExcluded() ? "1" : "0";
392 csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_TAX)] = taxonNode.isTaxonomicallyExcluded() ? "1" : "0";
393 csvLine[table.getIndex(CdmLightExportTable.EXCLUDED_NOM)] = taxonNode.isNomenclaturallyExcluded() ? "1" : "0";
394 csvLine[table.getIndex(CdmLightExportTable.UNCERTAIN_APPLICATION)] = taxonNode.isUncertainApplication() ? "1" : "0";
395 csvLine[table.getIndex(CdmLightExportTable.UNRESOLVED)] = taxonNode.isUnresolved() ? "1" : "0";
396 csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_STATUS)] = taxonNode.getStatus() == null ? null : taxonNode.getStatus().getLabel();
397 Map<Language, LanguageString> notesMap = taxonNode.getStatusNote();
398 String statusNotes = "";
399 if (!notesMap.isEmpty() && notesMap.size() == 1) {
400 statusNotes = notesMap.values().iterator().next().getText();
401 } else if (!notesMap.isEmpty()) {
402 statusNotes = notesMap.get(Language.getDefaultLanguage()) != null
403 ? notesMap.get(Language.getDefaultLanguage()).getText() : null;
404 if (statusNotes == null) {
405 statusNotes = notesMap.values().iterator().next().getText();
406 }
407 }
408 csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_NOTES)] = statusNotes;
409
410 if (taxonNode.getSource() != null) {
411 csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_REF_FK)] = getId(state, taxonNode.getSource().getCitation());
412 String sourceStr = OriginalSourceFormatter.INSTANCE.format(taxonNode.getSource());
413 csvLine[table.getIndex(CdmLightExportTable.PLACEMENT_REFERENCE)] = sourceStr;
414 }
415
416 //process taxon line
417 state.getProcessor().put(table, taxon, csvLine);
418
419 //descriptions
420 handleDescriptions(state, taxon);
421 } catch (Exception e) {
422 state.getResult().addException(e,
423 "An unexpected problem occurred when trying to export taxon with id " + taxon.getId() + " " + taxon.getTitleCache());
424 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
425 }
426 }
427 } catch (Exception e) {
428 state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of "
429 + cdmBaseStr(taxonNode.getTaxon()) + ", titleCache:"+ taxonNode.getTaxon().getTitleCache()+": " + e.getMessage());
430 }
431 }
432
433 private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
434 if (!state.getConfig().isDoFactualData()) {
435 return;
436 }
437 String titleCache = null;
438 try {
439
440 if (cdmBase instanceof Taxon) {
441 Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
442 titleCache = taxon.getTitleCache();
443 Set<TaxonDescription> descriptions = taxon.getDescriptions();
444 List<DescriptionElementBase> simpleFacts = new ArrayList<>();
445 List<DescriptionElementBase> specimenFacts = new ArrayList<>();
446 List<DescriptionElementBase> distributionFacts = new ArrayList<>();
447 List<DescriptionElementBase> taxonInteractionsFacts = new ArrayList<>();
448 List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
449 List<DescriptionElementBase> usageFacts = new ArrayList<>();
450 for (TaxonDescription description : descriptions) {
451 if (description.getElements() != null) {
452 for (DescriptionElementBase element : description.getElements()) {
453 element = CdmBase.deproxy(element);
454 handleAnnotations(element);
455 if (element.getFeature().equals(Feature.COMMON_NAME())) {
456 commonNameFacts.add(element);
457 } else if (element.getFeature().equals(Feature.DISTRIBUTION())) {
458 distributionFacts.add(element);
459 } else if (element instanceof IndividualsAssociation
460 || isSpecimenFeature(element.getFeature())) {
461 specimenFacts.add(element);
462 } else if (element.getFeature().isSupportsTaxonInteraction()) {
463 taxonInteractionsFacts.add(element);
464 } else {
465 simpleFacts.add(element);
466 }
467 }
468 }
469 }
470 if (!commonNameFacts.isEmpty()) {
471 handleCommonNameFacts(state, taxon, commonNameFacts);
472 }
473 if (!distributionFacts.isEmpty()) {
474 handleDistributionFacts(state, taxon, distributionFacts);
475 }
476 if (!specimenFacts.isEmpty()) {
477 handleSpecimenFacts(state, taxon, specimenFacts);
478 }
479 if (!simpleFacts.isEmpty()) {
480 handleSimpleFacts(state, taxon, simpleFacts);
481 }
482 if (!taxonInteractionsFacts.isEmpty()) {
483 handleTaxonInteractionsFacts(state, taxon, taxonInteractionsFacts);
484 }
485 } else if (cdmBase instanceof TaxonName) {
486 TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
487 titleCache = name.getTitleCache();
488 Set<TaxonNameDescription> descriptions = name.getDescriptions();
489 List<DescriptionElementBase> simpleFacts = new ArrayList<>();
490 for (TaxonNameDescription description : descriptions) {
491 if (description.getElements() != null) {
492 for (DescriptionElementBase element : description.getElements()) {
493 simpleFacts.add(element);
494 }
495 }
496 }
497 if (!simpleFacts.isEmpty()) {
498 handleSimpleFacts(state, name, simpleFacts);
499 }
500 }
501 } catch (Exception e) {
502 state.getResult().addException(e, "An unexpected error occurred when handling description of "
503 + cdmBaseStr(cdmBase) + (titleCache != null? (" " +titleCache) : "")+": " + e.getMessage());
504 }
505 }
506
507 private void handleAnnotations(DescriptionElementBase element) {
508 // TODO Auto-generated method stub
509 }
510
511 private void handleMetaData(CdmLightExportState state) {
512 CdmLightExportTable table = CdmLightExportTable.METADATA;
513 String[] csvLine = new String[table.getSize()];
514 // csvLine[table.getIndex(CdmLightExportTable.INSTANCE_ID)] = state.getConfig().getInctanceId();
515 // csvLine[table.getIndex(CdmLightExportTable.INSTANCE_NAME)] = state.getConfig().getInstanceName();
516 csvLine[table.getIndex(CdmLightExportTable.DATASET_BASE_URL)] = state.getConfig().getBase_url();
517 csvLine[table.getIndex(CdmLightExportTable.DATASET_CONTRIBUTOR)] = state.getConfig().getContributor();
518 csvLine[table.getIndex(CdmLightExportTable.DATASET_CREATOR)] = state.getConfig().getCreator();
519 csvLine[table.getIndex(CdmLightExportTable.DATASET_DESCRIPTION)] = state.getConfig().getDescription();
520 csvLine[table.getIndex(CdmLightExportTable.DATASET_DOWNLOAD_LINK)] = state.getConfig().getDataset_download_link();
521 csvLine[table.getIndex(CdmLightExportTable.DATASET_KEYWORDS)] = state.getConfig().getKeywords();
522 csvLine[table.getIndex(CdmLightExportTable.DATASET_LANDINGPAGE)] = state.getConfig().getDataSet_landing_page();
523
524 csvLine[table.getIndex(CdmLightExportTable.DATASET_LANGUAGE)] = state.getConfig().getLanguage() != null? state.getConfig().getLanguage().getLabel(): null;
525 csvLine[table.getIndex(CdmLightExportTable.DATASET_LICENCE)] = state.getConfig().getLicence();
526 csvLine[table.getIndex(CdmLightExportTable.DATASET_LOCATION)] = state.getConfig().getLocation();
527 csvLine[table.getIndex(CdmLightExportTable.DATASET_RECOMMENDED_CITATTION)] = state.getConfig().getRecommended_citation();
528 csvLine[table.getIndex(CdmLightExportTable.DATASET_TITLE)] = state.getConfig().getTitle();
529 state.getProcessor().put(table, "", csvLine);
530 }
531
532 private boolean isSpecimenFeature(Feature feature) {
533 // TODO allow user defined specimen features
534 if (feature == null) {
535 return false;
536 } else if (feature.isSupportsIndividualAssociation()) {
537 return true;
538 } else {
539 return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
540 || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
541 || feature.equals(Feature.OCCURRENCE());
542 }
543 }
544
545 private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
546 List<DescriptionElementBase> simpleFacts) {
547 String titleCache = null;
548 try {
549 CdmLightExportTable table;
550 if (cdmBase instanceof TaxonName) {
551 titleCache = ((TaxonName)cdmBase).getTitleCache();
552 table = CdmLightExportTable.NAME_FACT;
553 } else {
554 if (cdmBase instanceof Taxon){
555 titleCache = ((Taxon)cdmBase).getTitleCache();
556 }
557 table = CdmLightExportTable.SIMPLE_FACT;
558 }
559 CdmLightExportTable tableMedia = CdmLightExportTable.MEDIA;
560 for (DescriptionElementBase element : simpleFacts) {
561 if (element.getModifyingText().isEmpty() && !element.getMedia().isEmpty()) {
562 handleSimpleMediaFact(state, cdmBase, tableMedia, element);
563 } else {
564 handleSingleSimpleFact(state, cdmBase, table, element);
565 }
566 }
567 } catch (Exception e) {
568 state.getResult().addException(e, "An unexpected error occurred when handling simple facts for "
569 + cdmBaseStr(cdmBase) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
570 }
571 }
572
573 private void handleTaxonInteractionsFacts(CdmLightExportState state, CdmBase cdmBase,
574 List<DescriptionElementBase> taxonInteractionsFacts) {
575 CdmLightExportTable table = CdmLightExportTable.TAXON_INTERACTION_FACT;
576 String titleCache = null;
577 if (cdmBase instanceof TaxonBase){
578 titleCache = ((TaxonBase)cdmBase).getTitleCache();
579 }
580 for (DescriptionElementBase element : taxonInteractionsFacts) {
581
582 try {
583
584 String[] csvLine = new String[table.getSize()];
585
586 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
587 handleSource(state, element, table);
588 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
589 csvLine[table.getIndex(CdmLightExportTable.TAXON2_FK)] = getId(state,
590 ((TaxonInteraction) element).getTaxon2());
591 csvLine[table.getIndex(CdmLightExportTable.DESCRIPTION)] = createMultilanguageString(
592 ((TaxonInteraction) element).getDescription());
593 state.getProcessor().put(table, element, csvLine);
594
595 } catch (Exception e) {
596 state.getResult().addException(e, "An unexpected error occurred when handling taxon interaction"
597 + cdmBaseStr(element) + (titleCache != null? (" " +titleCache) : "")+ ": " + e.getMessage());
598 }
599 }
600 }
601
602 private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
603 DescriptionElementBase element) {
604 try {
605 String[] csvLine;
606 handleSource(state, element, CdmLightExportTable.MEDIA);
607
608 if (element instanceof TextData) {
609 TextData textData = (TextData) element;
610 csvLine = new String[table.getSize()];
611 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
612 if (cdmBase instanceof Taxon) {
613 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
614 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
615 } else if (cdmBase instanceof TaxonName) {
616 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
617 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
618 }
619
620 String mediaUris = "";
621 for (Media media : textData.getMedia()) {
622 String mediaString = extractMediaUris(media.getRepresentations().iterator());
623 if (!StringUtils.isBlank(mediaString)) {
624 mediaUris += mediaString + ";";
625 } else {
626 state.getResult().addWarning("Empty Media object for " + cdmBase.getUserFriendlyTypeName() + " "
627 + cdmBase.getUuid() + " (media: " + media.getUuid() + ")");
628 }
629 }
630 csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
631
632 }
633 } catch (Exception e) {
634 state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
635 + cdmBaseStr(element) + ": " + e.getMessage());
636 }
637
638 }
639
640 private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
641 DescriptionElementBase element) {
642 try {
643 String[] csvLine;
644 handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
645
646 if (element instanceof TextData) {
647 TextData textData = (TextData) element;
648 csvLine = new String[table.getSize()];
649 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
650 if (cdmBase instanceof Taxon) {
651 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
652 } else if (cdmBase instanceof TaxonName) {
653 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
654 }
655 csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
656
657 String mediaUris = "";
658 for (Media media : textData.getMedia()) {
659 String mediaString = extractMediaUris(media.getRepresentations().iterator());
660 if (!StringUtils.isBlank(mediaString)) {
661 mediaUris += mediaString + ";";
662 } else {
663 state.getResult().addWarning("Empty Media object for uuid: " + cdmBase.getUuid()
664 + " uuid of media: " + media.getUuid());
665 }
666 }
667 csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
668 if (textData.getFeature().equals(Feature.CITATION())) {
669 state.getProcessor().put(table, textData, csvLine);
670 } else if (!textData.getMultilanguageText().isEmpty()) {
671 for (Language language : textData.getMultilanguageText().keySet()) {
672 String[] csvLineLanguage = csvLine.clone();
673 LanguageString langString = textData.getLanguageText(language);
674 String text = langString.getText();
675 if (state.getConfig().isFilterIntextReferences()) {
676 text = filterIntextReferences(langString.getText());
677 }
678 csvLineLanguage[table.getIndex(CdmLightExportTable.FACT_TEXT)] = text;
679 csvLineLanguage[table.getIndex(CdmLightExportTable.LANGUAGE)] = language.getLabel();
680 state.getProcessor().put(table, textData, csvLineLanguage);
681 }
682 } else {
683 state.getProcessor().put(table, textData, csvLine);
684 }
685 }else if (element instanceof CategoricalData) {
686 //use formater
687 CategoricalData categoricalData = (CategoricalData)element;
688 String cache = CategoricalDataFormatter.NewInstance(null).format(categoricalData);
689 csvLine = new String[table.getSize()];
690 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
691 if (cdmBase instanceof Taxon) {
692 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
693 } else if (cdmBase instanceof TaxonName) {
694 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
695 }
696 csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = cache;
697 csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = categoricalData.getFeature().getLabel();
698 state.getProcessor().put(table, categoricalData, csvLine);
699 }else if (element instanceof QuantitativeData) {
700 QuantitativeData quantitativeData = (QuantitativeData) element;
701 String cache = QuantitativeDataFormatter.NewInstance(null).format(quantitativeData);
702 csvLine = new String[table.getSize()];
703 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
704 if (cdmBase instanceof Taxon) {
705 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
706 } else if (cdmBase instanceof TaxonName) {
707 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
708 }
709 csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = cache;
710 csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = quantitativeData.getFeature().getLabel();
711 state.getProcessor().put(table, quantitativeData, csvLine);
712 }
713 } catch (Exception e) {
714 state.getResult().addException(e, "An unexpected error occurred when handling single simple fact "
715 + cdmBaseStr(element) + ": " + e.getMessage());
716 }
717 }
718
719 private String filterIntextReferences(String text) {
720 /*
721 * (<cdm:reference cdmId='fbd19251-efee-4ded-b780-915000f66d41'
722 * intextId='1352d42c-e201-4155-a02a-55360d3b563e'>Ridley in Fl. Malay
723 * Pen. 3 (1924) 22</cdm:reference>)
724 */
725 String newText = text.replaceAll("<cdm:reference cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
726 newText = newText.replaceAll("</cdm:reference>", "");
727
728 newText = newText.replaceAll("<cdm:key cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>", "");
729 newText = newText.replaceAll("</cdm:key>", "");
730 return newText;
731 }
732
733 private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon,
734 List<DescriptionElementBase> specimenFacts) {
735 CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
736
737 for (DescriptionElementBase element : specimenFacts) {
738 try {
739 String[] csvLine = new String[table.getSize()];
740 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
741 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
742 handleSource(state, element, table);
743 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(
744 element.getAnnotations());
745
746 if (element instanceof IndividualsAssociation) {
747
748 IndividualsAssociation indAssociation = (IndividualsAssociation) element;
749 if (indAssociation.getAssociatedSpecimenOrObservation() == null) {
750 state.getResult()
751 .addWarning("There is an individual association with no specimen associated (Taxon "
752 + taxon.getTitleCache() + "(" + taxon.getUuid() + "). Could not be exported.");
753 continue;
754 } else {
755 if (!state.getSpecimenStore()
756 .contains((indAssociation.getAssociatedSpecimenOrObservation().getUuid()))) {
757 SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(
758 indAssociation.getAssociatedSpecimenOrObservation(),
759 SpecimenOrObservationBase.class);
760
761 handleSpecimen(state, specimenBase);
762 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state,
763 indAssociation.getAssociatedSpecimenOrObservation());
764 }
765 }
766 } else if (element instanceof TextData) {
767 TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
768 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(
769 textData.getMultilanguageText());
770 }
771 state.getProcessor().put(table, element, csvLine);
772 } catch (Exception e) {
773 state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact "
774 + cdmBaseStr(element) + ": " + e.getMessage());
775 }
776 }
777 }
778
779 private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
780 String text = "";
781 int index = multilanguageText.size();
782 for (LanguageString langString : multilanguageText.values()) {
783 text += langString.getText();
784 if (index > 1) {
785 text += "; ";
786 }
787 index--;
788 }
789 return text;
790 }
791
792 private String createAnnotationsString(Set<Annotation> annotations) {
793 StringBuffer strBuff = new StringBuffer();
794
795 for (Annotation ann : annotations) {
796 if (ann.getAnnotationType() == null || !ann.getAnnotationType().equals(AnnotationType.TECHNICAL())) {
797 strBuff.append(ann.getText());
798 strBuff.append("; ");
799 }
800 }
801
802 if (strBuff.length() > 2) {
803 return strBuff.substring(0, strBuff.length() - 2);
804 } else {
805 return null;
806 }
807 }
808
809 private void handleSource(CdmLightExportState state, DescriptionElementBase element,
810 CdmLightExportTable factsTable) {
811 CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
812 try {
813 Set<DescriptionElementSource> sources = element.getSources();
814
815 for (DescriptionElementSource source : sources) {
816 if (!(source.getType().equals(OriginalSourceType.Import)
817 && state.getConfig().isExcludeImportSources())) {
818 String[] csvLine = new String[table.getSize()];
819 Reference ref = source.getCitation();
820 if ((ref == null) && (source.getNameUsedInSource() == null)) {
821 continue;
822 }
823 if (ref != null) {
824 if (!state.getReferenceStore().contains(ref.getUuid())) {
825 handleReference(state, ref);
826
827 }
828 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
829 }
830 csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
831
832 csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state,
833 source.getNameUsedInSource());
834 csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
835 if (StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)])
836 && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])) {
837 continue;
838 }
839 state.getProcessor().put(table, source, csvLine);
840 }
841 }
842 } catch (Exception e) {
843 state.getResult().addException(e, "An unexpected error occurred when handling single source "
844 + cdmBaseStr(element) + ": " + e.getMessage());
845 }
846 }
847
848 private void handleDistributionFacts(CdmLightExportState state, Taxon taxon,
849 List<DescriptionElementBase> distributionFacts) {
850
851 CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
852 Set<Distribution> distributions = new HashSet<>();
853 for (DescriptionElementBase element : distributionFacts) {
854 try {
855 if (element instanceof Distribution) {
856 String[] csvLine = new String[table.getSize()];
857 Distribution distribution = (Distribution) element;
858 distributions.add(distribution);
859 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
860 handleSource(state, element, table);
861 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
862 if (distribution.getArea() != null) {
863 csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = distribution.getArea().getLabel();
864 }
865 if (distribution.getStatus() != null) {
866 csvLine[table.getIndex(CdmLightExportTable.STATUS_LABEL)] = distribution.getStatus().getLabel();
867 }
868 state.getProcessor().put(table, distribution, csvLine);
869 } else {
870 state.getResult()
871 .addError("The distribution description for the taxon " + taxon.getUuid()
872 + " is not of type distribution. Could not be exported. UUID of the description element: "
873 + element.getUuid());
874 }
875 } catch (Exception e) {
876 state.getResult().addException(e, "An unexpected error occurred when handling single distribution "
877 + cdmBaseStr(element) + ": " + e.getMessage());
878 }
879 }
880 if(state.getConfig().isCreateCondensedDistributionString()){
881 List<Language> langs = new ArrayList<>();
882 langs.add(Language.ENGLISH());
883 TermTree<NamedArea> areaTree = null; //TODO
884
885 CondensedDistribution conDis = distributionService.getCondensedDistribution(
886 //TODO add CondensedDistributionConfiguration to export configuration
887 distributions, areaTree, true, null, state.getConfig().getCondensedDistributionConfiguration(), langs);
888 CdmLightExportTable tableCondensed =
889 CdmLightExportTable.SIMPLE_FACT;
890 String[] csvLine = new String[tableCondensed.getSize()];
891 //the computed fact has no uuid, TODO: remember the uuid for later reference assignment
892 UUID randomUuid = UUID.randomUUID();
893 csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_ID)] =
894 randomUuid.toString();
895 csvLine[tableCondensed.getIndex(CdmLightExportTable.TAXON_FK)] =
896 getId(state, taxon);
897 csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_TEXT)] =
898 conDis.toString();
899 csvLine[tableCondensed.getIndex(CdmLightExportTable.LANGUAGE)] =Language.ENGLISH().toString();
900
901 csvLine[tableCondensed.getIndex(CdmLightExportTable.FACT_CATEGORY)] =
902 "CondensedDistribution";
903
904 state.getProcessor().put(tableCondensed, taxon, csvLine);
905 }
906 }
907
908 private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon,
909 List<DescriptionElementBase> commonNameFacts) {
910 CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
911
912 for (DescriptionElementBase element : commonNameFacts) {
913 try {
914 if (element instanceof CommonTaxonName) {
915 String[] csvLine = new String[table.getSize()];
916 CommonTaxonName commonName = (CommonTaxonName) element;
917 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
918 handleSource(state, element, table);
919 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
920 if (commonName.getName() != null) {
921 csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();
922 }
923 if (commonName.getLanguage() != null) {
924 csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();
925 }
926 if (commonName.getArea() != null) {
927 csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();
928 }
929 state.getProcessor().put(table, commonName, csvLine);
930 } else if (element instanceof TextData){
931 String[] csvLine = new String[table.getSize()];
932 TextData commonName = (TextData) element;
933 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
934 handleSource(state, element, table);
935 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
936 if (commonName.getMultilanguageText() != null) {
937 csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = createMultilanguageString(commonName.getMultilanguageText());
938 }
939 state.getProcessor().put(table, commonName, csvLine);
940 } else {
941 state.getResult()
942 .addError("The common name description for the taxon " + taxon.getUuid()
943 + " is not of type common name. Could not be exported. UUID of the description element: "
944 + element.getUuid());
945 }
946 } catch (Exception e) {
947 state.getResult().addException(e, "An unexpected error occurred when handling single common name "
948 + cdmBaseStr(element) + " - "+taxon.getTitleCache()+ ": " + e.getMessage());
949 }
950 }
951 }
952
953 private String getTitleCache(IIdentifiableEntity identEntity) {
954 if (identEntity == null) {
955 return "";
956 }
957 // TODO refresh?
958 return identEntity.getTitleCache();
959 }
960
961 private String getId(CdmLightExportState state, ICdmBase cdmBase) {
962 if (cdmBase == null) {
963 return "";
964 }
965 // TODO make configurable
966 return cdmBase.getUuid().toString();
967 }
968
969 private void handleSynonym(CdmLightExportState state, Synonym synonym, int index) {
970 try {
971 if (isUnpublished(state.getConfig(), synonym)) {
972 return;
973 }
974 TaxonName name = synonym.getName();
975 handleName(state, name, synonym.getAcceptedTaxon());
976
977 CdmLightExportTable table = CdmLightExportTable.SYNONYM;
978 String[] csvLine = new String[table.getSize()];
979
980 csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, synonym);
981 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, synonym.getAcceptedTaxon());
982 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
983 if (synonym.getSec() != null && !state.getReferenceStore().contains(synonym.getSec().getUuid())) {
984 handleReference(state, synonym.getSec());
985 }
986 csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = synonym.getAppendedPhrase();
987 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synonym.getSec());
988 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synonym.getSec());
989 csvLine[table.getIndex(CdmLightExportTable.PUBLISHED)] = synonym.isPublish() ? "1" : "0";
990 csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = "0";
991 csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = "0";
992 csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = "0";
993 csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
994 state.getProcessor().put(table, synonym, csvLine);
995 } catch (Exception e) {
996 state.getResult().addException(e, "An unexpected error occurred when handling synonym "
997 + cdmBaseStr(synonym) + ": " + e.getMessage());
998 }
999 }
1000
1001 /**
1002 * Handles misapplied names (including pro parte and partial as well as pro
1003 * parte and partial synonyms
1004 */
1005 private void handleProPartePartialMisapplied(CdmLightExportState state, Taxon taxon, Taxon accepted, boolean isProParte, boolean isMisapplied, int index) {
1006 try {
1007 Taxon ppSyonym = taxon;
1008 if (isUnpublished(state.getConfig(), ppSyonym)) {
1009 return;
1010 }
1011 TaxonName name = ppSyonym.getName();
1012 handleName(state, name, accepted);
1013
1014 CdmLightExportTable table = CdmLightExportTable.SYNONYM;
1015 String[] csvLine = new String[table.getSize()];
1016
1017 csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, ppSyonym);
1018 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, accepted);
1019 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
1020
1021 Reference secRef = ppSyonym.getSec();
1022
1023 if (secRef != null && !state.getReferenceStore().contains(secRef.getUuid())) {
1024 handleReference(state, secRef);
1025 }
1026 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
1027 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
1028 Set<TaxonRelationship> rels = accepted.getTaxonRelations(ppSyonym);
1029 TaxonRelationship rel = null;
1030 boolean isPartial = false;
1031 if (rels.size() == 1){
1032 rel = rels.iterator().next();
1033
1034 }else if (rels.size() > 1){
1035 Iterator<TaxonRelationship> iterator = rels.iterator();
1036 while (iterator.hasNext()){
1037 rel = iterator.next();
1038 if (isProParte && rel.getType().isAnySynonym()){
1039 break;
1040 } else if (isMisapplied && rel.getType().isAnyMisappliedName()){
1041 break;
1042 }else{
1043 rel = null;
1044 }
1045 }
1046 }
1047 if (rel != null){
1048 Reference synSecRef = rel.getCitation();
1049 if (synSecRef != null && !state.getReferenceStore().contains(synSecRef.getUuid())) {
1050 handleReference(state, synSecRef);
1051 }
1052 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
1053 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
1054 isProParte = rel.getType().isProParte();
1055 isPartial = rel.getType().isPartial();
1056
1057 }else{
1058 state.getResult().addWarning("An unexpected error occurred when handling "
1059 + "pro parte/partial synonym or misapplied name " + cdmBaseStr(taxon) );
1060 }
1061
1062 // pro parte type
1063
1064 csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = isProParte ? "1" : "0";
1065 csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = isPartial ? "1" : "0";
1066 csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = isMisapplied ? "1" : "0";
1067 csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(index);
1068 state.getProcessor().put(table, ppSyonym, csvLine);
1069 } catch (Exception e) {
1070 state.getResult().addException(e, "An unexpected error occurred when handling "
1071 + "pro parte/partial synonym or misapplied name " + cdmBaseStr(taxon) + ": " + e.getMessage());
1072 }
1073
1074 }
1075
1076 private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon){
1077 handleName(state, name, acceptedTaxon, false);
1078 }
1079
1080 private void handleName(CdmLightExportState state, TaxonName name, Taxon acceptedTaxon, boolean acceptedName) {
1081 if (name == null || state.getNameStore().containsKey(name.getId())) {
1082 return;
1083 }
1084 try {
1085 Rank rank = name.getRank();
1086 CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
1087 name = HibernateProxyHelper.deproxy(name);
1088 state.getNameStore().put(name.getId(), name.getUuid());
1089 String[] csvLine = new String[table.getSize()];
1090
1091 csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
1092 if (name.getLsid() != null) {
1093 csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
1094 } else {
1095 csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
1096 }
1097
1098 handleIdentifier(state, name);
1099 handleDescriptions(state, name);
1100
1101 csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
1102 if (rank != null) {
1103 csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
1104 if (rank.isInfraGeneric()) {
1105 try {
1106 csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank()
1107 .getInfraGenericMarker();
1108 } catch (UnknownCdmTypeException e) {
1109 state.getResult().addError("Infrageneric marker expected but not available for rank "
1110 + name.getRank().getTitleCache());
1111 }
1112 }
1113 if (rank.isInfraSpecific()) {
1114 csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
1115 }
1116 } else {
1117 csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
1118 }
1119 if (name.isProtectedTitleCache()) {
1120 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
1121 } else {
1122 // TODO: adapt the tropicos titlecache creation
1123 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
1124 }
1125
1126
1127 if (!state.getConfig().isAddHTML()) {
1128 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = name.getFullTitleCache();
1129 } else {
1130 List<TaggedText> taggedFullTitleCache = name.getTaggedFullTitle();
1131 List<TaggedText> taggedName = name.getTaggedName();
1132
1133 String fullTitleWithHtml = createNameWithItalics(taggedFullTitleCache);
1134 // TODO: adapt the tropicos titlecache creation
1135 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_REF)] = fullTitleWithHtml.trim();
1136 }
1137
1138 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
1139 csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
1140
1141 csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
1142 csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
1143
1144 csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
1145
1146 csvLine[table.getIndex(CdmLightExportTable.APPENDED_PHRASE)] = name.getAppendedPhrase();
1147
1148 csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state, name.getBasionymAuthorship());
1149 if (name.getBasionymAuthorship() != null) {
1150 if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
1151 handleAuthor(state, name.getBasionymAuthorship());
1152 }
1153 }
1154 csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state,
1155 name.getExBasionymAuthorship());
1156 if (name.getExBasionymAuthorship() != null) {
1157 if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
1158 handleAuthor(state, name.getExBasionymAuthorship());
1159 }
1160
1161 }
1162 csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,
1163 name.getCombinationAuthorship());
1164 if (name.getCombinationAuthorship() != null) {
1165 if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
1166 handleAuthor(state, name.getCombinationAuthorship());
1167 }
1168 }
1169 csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state,
1170 name.getExCombinationAuthorship());
1171 if (name.getExCombinationAuthorship() != null) {
1172 if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
1173 handleAuthor(state, name.getExCombinationAuthorship());
1174 }
1175
1176 }
1177
1178 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
1179
1180 Reference nomRef = name.getNomenclaturalReference();
1181
1182 NomenclaturalSource nomenclaturalSource = name.getNomenclaturalSource();
1183 if (nomenclaturalSource != null &&nomenclaturalSource.getNameUsedInSource() != null){
1184 handleName(state, nomenclaturalSource.getNameUsedInSource(), null);
1185 csvLine[table.getIndex(CdmLightExportTable.NAME_USED_IN_SOURCE_FK)] = getId(state, nomenclaturalSource.getNameUsedInSource());
1186 }
1187
1188 if (nomRef != null) {
1189 if (!state.getReferenceStore().contains(nomRef.getUuid())) {
1190 handleReference(state, nomRef);
1191 }
1192 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
1193 csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
1194 if (nomRef.getVolume() != null) {
1195 csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
1196 csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollation(name);
1197 }
1198 if (nomRef.getDatePublished() != null) {
1199 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
1200 csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
1201 csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = nomRef.getDatePublished()
1202 .getVerbatimDate();
1203 }
1204 if (name.getNomenclaturalMicroReference() != null) {
1205 csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
1206 }
1207 nomRef = HibernateProxyHelper.deproxy(nomRef);
1208 if (nomRef.getInReference() != null) {
1209 Reference inReference = nomRef.getInReference();
1210 if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null) {
1211 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference
1212 .getDatePublishedString();
1213 csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished()
1214 .getYear();
1215 }
1216 if (nomRef.getVolume() == null && inReference.getVolume() != null) {
1217 csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
1218 csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollation(name);
1219 }
1220 if (inReference.getInReference() != null) {
1221 inReference = inReference.getInReference();
1222 }
1223 if (inReference.getAbbrevTitle() == null) {
1224 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1225 .Nz(inReference.getTitle());
1226 } else {
1227 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1228 .Nz(inReference.getAbbrevTitle());
1229 }
1230 if (inReference.getTitle() == null) {
1231 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils
1232 .Nz(inReference.getAbbrevTitle()!= null? inReference.getAbbrevTitle(): inReference.getTitleCache());
1233 } else {
1234 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
1235 }
1236
1237 TeamOrPersonBase<?> author = inReference.getAuthorship();
1238 if (author != null
1239 && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))) {
1240 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1241 ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitleCache());
1242 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1243 .Nz(author.getTitleCache());
1244 } else {
1245 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1246 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1247 }
1248 } else {
1249 if (nomRef.getAbbrevTitle() == null) {
1250 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1251 .Nz(nomRef.getTitle()!= null? nomRef.getTitle():nomRef.getAbbrevTitleCache());
1252 } else {
1253 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils
1254 .Nz(nomRef.getAbbrevTitle());
1255 }
1256 if (nomRef.getTitle() == null) {
1257 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils
1258 .Nz(nomRef.getAbbrevTitle()!= null? nomRef.getAbbrevTitle(): nomRef.getTitleCache());
1259 } else {
1260 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
1261 }
1262 TeamOrPersonBase<?> author = nomRef.getAuthorship();
1263 if (author != null) {
1264 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = author.isProtectedTitleCache()
1265 ? author.getTitleCache() : CdmUtils.Nz(author.getNomenclaturalTitleCache());
1266 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils
1267 .Nz(author.getTitleCache());
1268 } else {
1269 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
1270 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
1271 }
1272
1273 }
1274 } else {
1275 csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
1276 }
1277
1278 /*
1279 * Collation
1280 *
1281 * Detail
1282 *
1283 * TitlePageYear
1284 */
1285 String protologueUriString = extractProtologueURIs(state, name);
1286
1287 csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
1288 Collection<TypeDesignationBase> specimenTypeDesignations = new ArrayList<>();
1289 List<TextualTypeDesignation> textualTypeDesignations = new ArrayList<>();
1290 for (TypeDesignationBase<?> typeDesignation : name.getTypeDesignations()) {
1291 if (typeDesignation.isInstanceOf(TextualTypeDesignation.class)) {
1292
1293 if (((TextualTypeDesignation) typeDesignation).isVerbatim() ){
1294 Set<IdentifiableSource> sources = typeDesignation.getSources();
1295 boolean isProtologue = false;
1296 if (sources != null && !sources.isEmpty()){
1297 IdentifiableSource source = sources.iterator().next();
1298 if (name.getNomenclaturalReference() != null){
1299 isProtologue = source.getCitation() != null? source.getCitation().getUuid().equals(name.getNomenclaturalReference().getUuid()): false;
1300 }
1301 }
1302 if (isProtologue){
1303 csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_TYPE_STATEMENT)] = ((TextualTypeDesignation) typeDesignation)
1304 .getPreferredText(Language.DEFAULT());
1305 }else{
1306 textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1307 }
1308
1309 } else {
1310 textualTypeDesignations.add((TextualTypeDesignation) typeDesignation);
1311 }
1312 } else if (typeDesignation.isInstanceOf(SpecimenTypeDesignation.class)) {
1313 SpecimenTypeDesignation specimenType = HibernateProxyHelper.deproxy(typeDesignation, SpecimenTypeDesignation.class);
1314 specimenTypeDesignations.add(specimenType);
1315 handleSpecimenType(state, specimenType);
1316
1317
1318 }else if (typeDesignation instanceof NameTypeDesignation){
1319 specimenTypeDesignations.add(HibernateProxyHelper.deproxy(typeDesignation, NameTypeDesignation.class));
1320 }
1321 }
1322 TypeDesignationSetContainer manager = new TypeDesignationSetContainer(specimenTypeDesignations, name, TypeDesignationSetComparator.ORDER_BY.TYPE_STATUS);
1323 HTMLTagRules rules = new HTMLTagRules();
1324 rules.addRule(TagEnum.name, "i");
1325 csvLine[table.getIndex(CdmLightExportTable.TYPE_SPECIMEN)] = manager.print(false, false, false, rules);
1326
1327 StringBuilder stringbuilder = new StringBuilder();
1328 int i = 1;
1329 for (TextualTypeDesignation typeDesignation : textualTypeDesignations) {
1330 stringbuilder.append(typeDesignation.getPreferredText(Language.DEFAULT()));
1331 if (typeDesignation.getSources() != null && !typeDesignation.getSources().isEmpty() ){
1332 stringbuilder.append( " [");
1333 int index = 1;
1334 for (IdentifiableSource source: typeDesignation.getSources()){
1335 if (source.getCitation() != null){
1336 stringbuilder.append(OriginalSourceFormatter.INSTANCE.format(source));
1337 }
1338 if (index < typeDesignation.getSources().size()) {
1339 stringbuilder.append( ", ");
1340 }
1341 index++;
1342 }
1343 stringbuilder.append( "]");
1344 }
1345 if (i < textualTypeDesignations.size()) {
1346 stringbuilder.append( "; ");
1347 } else {
1348 stringbuilder.append(".");
1349 }
1350 i++;
1351 }
1352 csvLine[table.getIndex(CdmLightExportTable.TYPE_STATEMENT)] = stringbuilder.toString();
1353
1354
1355 if (name.getStatus() == null || name.getStatus().isEmpty()) {
1356 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
1357 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
1358 } else {
1359
1360 String statusStringAbbrev = extractStatusString(state, name, true);
1361 String statusString = extractStatusString(state, name, false);
1362
1363 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
1364 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
1365 }
1366
1367 HomotypicalGroup group = HibernateProxyHelper.deproxy(name.getHomotypicalGroup(), HomotypicalGroup.class);
1368
1369 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
1370 List<TaxonName> typifiedNames = new ArrayList<>();
1371 if (acceptedTaxon != null){
1372 HomotypicGroupTaxonComparator comparator = new HomotypicGroupTaxonComparator(acceptedTaxon);
1373 List<Synonym> synonymsInGroup = null;
1374 if (group.equals(acceptedTaxon.getHomotypicGroup())){
1375 synonymsInGroup = acceptedTaxon.getHomotypicSynonymsByHomotypicGroup(comparator);
1376 typifiedNames.add(name);
1377 }else{
1378 synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group, comparator);
1379 }
1380
1381 synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(HibernateProxyHelper.deproxy(synonym.getName())));
1382
1383 }else{
1384 typifiedNames.addAll(group.getTypifiedNames());
1385 }
1386
1387 Integer seqNumber = typifiedNames.indexOf(name);
1388 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1389 state.getProcessor().put(table, name, csvLine);
1390 handleNameRelationships(state, name);
1391
1392 } catch (Exception e) {
1393 state.getResult().addException(e,
1394 "An unexpected error occurred when handling the name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1395
1396 e.printStackTrace();
1397 }
1398 }
1399
1400 private void handleSpecimenType_(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1401 if (specimenType.getTypeSpecimen() != null){
1402 DerivedUnit specimen = specimenType.getTypeSpecimen();
1403 if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1404 handleSpecimen(state, specimen);
1405 }
1406 }
1407 CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1408 String[] csvLine = new String[table.getSize()];
1409 //TYPE_ID, SPECIMEN_FK, TYPE_VERBATIM_CITATION, TYPE_STATUS, TYPE_DESIGNATED_BY_STRING, TYPE_DESIGNATED_BY_REF_FK};
1410 //Specimen_Fk und den Typusangaben (Art des Typus [holo, lecto, etc.], Quelle, Designation-Quelle, +
1411 Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1412 for (TaxonName name: typifiedNames){
1413 csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1414 csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
1415 csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1416 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1417 if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1418 String sourceString = "";
1419 int index = 0;
1420 for (IdentifiableSource source: specimenType.getSources()){
1421 if (source.getCitation()!= null){
1422 sourceString = sourceString.concat(source.getCitation().getCitation());
1423 }
1424 index++;
1425 if (index != specimenType.getSources().size()){
1426 sourceString.concat(", ");
1427 }
1428 }
1429 csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1430 }
1431 if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1432 handleReference(state, specimenType.getDesignationSource().getCitation());
1433 csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1434 }
1435
1436 state.getProcessor().put(table, specimenType, csvLine);
1437 }
1438 }
1439
1440
1441 /**
1442 * @param specimenType
1443 */
1444 private void handleSpecimenType(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1445 if (specimenType.getTypeSpecimen() != null){
1446 DerivedUnit specimen = specimenType.getTypeSpecimen();
1447 if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1448 handleSpecimen(state, specimen);
1449 }
1450 }
1451 CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1452 String[] csvLine = new String[table.getSize()];
1453
1454 csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1455 csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
1456 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1457 if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1458 String sourceString = "";
1459 int index = 0;
1460 List<IdentifiableSource> sources = new ArrayList<>(specimenType.getSources());
1461 Comparator<IdentifiableSource> compareByYear = new Comparator<IdentifiableSource>() {
1462 @Override
1463 public int compare(IdentifiableSource o1, IdentifiableSource o2) {
1464 if (o1 == o2){
1465 return 0;
1466 }
1467 if (o1.getCitation() == null && o2.getCitation() != null){
1468 return -1;
1469 }
1470 if (o2.getCitation() == null && o1.getCitation() != null){
1471 return 1;
1472 }
1473 if (o1.getCitation().equals(o2.getCitation())){
1474 return 0;
1475 }
1476 if (o1.getCitation().getDatePublished() == null && o2.getCitation().getDatePublished() != null){
1477 return -1;
1478 }
1479 if (o1.getCitation().getDatePublished() != null && o2.getCitation().getDatePublished() == null){
1480 return 1;
1481 }
1482 if (o1.getCitation().getDatePublished().getYear() == null && o2.getCitation().getDatePublished().getYear() != null){
1483 return -1;
1484 }
1485 if (o1.getCitation().getDatePublished().getYear() != null && o2.getCitation().getDatePublished().getYear() == null){
1486 return 1;
1487 }
1488 return o1.getCitation().getDatePublished().getYear().compareTo(o2.getCitation().getDatePublished().getYear());
1489 }
1490 };
1491 Collections.sort(sources, compareByYear);
1492 for (IdentifiableSource source: sources){
1493 if (source.getCitation()!= null){
1494 sourceString = sourceString.concat(source.getCitation().getCitation());
1495 handleReference(state, source.getCitation());
1496 }
1497 index++;
1498 if (index <= specimenType.getSources().size()){
1499 sourceString = sourceString.concat("; ");
1500 }
1501 }
1502
1503 csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1504 if (sources.get(0).getCitation() != null ){
1505 csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_FK)] = getId(state, sources.get(0).getCitation());
1506 }
1507 }
1508 if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1509 handleReference(state, specimenType.getDesignationSource().getCitation());
1510 csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1511 }
1512
1513
1514 Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1515
1516 if (typifiedNames.size() > 1){
1517 state.getResult().addWarning("Please check the specimen type "
1518 + cdmBaseStr(specimenType) + " there are more then one typified name.");
1519 }
1520 if (typifiedNames.iterator().hasNext()){
1521 TaxonName name = typifiedNames.iterator().next();
1522 csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1523 }
1524 state.getProcessor().put(table, specimenType, csvLine);
1525 }
1526
1527 private String createNameWithItalics(List<TaggedText> taggedName) {
1528
1529 String fullTitleWithHtml = "";
1530 for (TaggedText taggedText: taggedName){
1531 if (taggedText.getType().equals(TagEnum.name)){
1532 fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1533 }else if (taggedText.getType().equals(TagEnum.separator)){
1534 fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1535 }else{
1536 fullTitleWithHtml += taggedText.getText() + " ";
1537 }
1538 }
1539 return fullTitleWithHtml;
1540 }
1541
1542 private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1543 Set<NameRelationship> rels = name.getRelationsFromThisName();
1544 CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1545 String[] csvLine = new String[table.getSize()];
1546
1547 for (NameRelationship rel : rels) {
1548 NameRelationshipType type = rel.getType();
1549 TaxonName name2 = rel.getToName();
1550 name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1551 if (!state.getNameStore().containsKey(name2.getId())) {
1552 handleName(state, name2, null);
1553 }
1554 csvLine = new String[table.getSize()];
1555 csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1556 csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1557 csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1558 state.getProcessor().put(table, rel.getUuid().toString(), csvLine);
1559 }
1560
1561 rels = name.getRelationsToThisName();
1562
1563 csvLine = new String[table.getSize()];
1564
1565 for (NameRelationship rel : rels) {
1566 TaxonName name2 = rel.getFromName();
1567 name2 = HibernateProxyHelper.deproxy(name2);
1568 if (!state.getNameStore().containsKey(name2.getId())) {
1569 handleName(state, name2, null);
1570 }
1571 }
1572 }
1573
1574 private String createCollation(TaxonName name) {
1575 String collation = "";
1576 if (name.getNomenclaturalReference() != null) {
1577 Reference ref = name.getNomenclaturalReference();
1578 collation = getVolume(ref);
1579 }
1580 if (name.getNomenclaturalMicroReference() != null) {
1581 if (!StringUtils.isBlank(collation)) {
1582 collation += ":";
1583 }
1584 collation += name.getNomenclaturalMicroReference();
1585 }
1586
1587 return collation;
1588 }
1589
1590 private String getVolume(Reference reference) {
1591 if (reference.getVolume() != null) {
1592 return reference.getVolume();
1593 } else if (reference.getInReference() != null) {
1594 if (reference.getInReference().getVolume() != null) {
1595 return reference.getInReference().getVolume();
1596 }
1597 }
1598 return null;
1599 }
1600
1601 private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1602 CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1603 String[] csvLine;
1604 try {
1605 if (cdmBase instanceof TaxonName){
1606 TaxonName name = (TaxonName)cdmBase;
1607
1608 try{
1609 List<Identifier> identifiers = name.getIdentifiers();
1610
1611 //first check which kind of identifiers are available and then sort and create table entries
1612 Map<IdentifierType, Set<Identifier>> identifierTypes = new HashMap<>();
1613 for (Identifier identifier: identifiers){
1614 IdentifierType type = identifier.getType();
1615 if (identifierTypes.containsKey(type)){
1616 identifierTypes.get(type).add(identifier);
1617 }else{
1618 Set<Identifier> tempList = new HashSet<>();
1619 tempList.add(identifier);
1620 identifierTypes.put(type, tempList);
1621 }
1622 }
1623
1624 for (IdentifierType type:identifierTypes.keySet()){
1625 Set<Identifier> identifiersByType = identifierTypes.get(type);
1626 csvLine = new String[table.getSize()];
1627 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1628 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1629 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = type.getLabel();
1630 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1631 identifiersByType);
1632 state.getProcessor().put(table, name.getUuid() + ", " + type.getLabel(), csvLine);
1633 }
1634
1635
1636 // Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1637 // Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1638 // Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1639 // if (!IPNIidentifiers.isEmpty()) {
1640 // csvLine = new String[table.getSize()];
1641 // csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1642 // csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1643 // csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1644 // csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1645 // IPNIidentifiers);
1646 // state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1647 // }
1648 // if (!tropicosIdentifiers.isEmpty()) {
1649 // csvLine = new String[table.getSize()];
1650 // csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1651 // csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1652 // csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
1653 // csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1654 // tropicosIdentifiers);
1655 // state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1656 // }
1657 // if (!WFOIdentifiers.isEmpty()) {
1658 // csvLine = new String[table.getSize()];
1659 // csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1660 // csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1661 // csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1662 // csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1663 // WFOIdentifiers);
1664 // state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1665 // }
1666 }catch(Exception e){
1667 state.getResult().addWarning("Please check the identifiers for "
1668 + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1669
1670
1671 }
1672 }else{
1673 if (cdmBase instanceof IdentifiableEntity){
1674 IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1675 List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1676 String tableName = null;
1677 if (cdmBase instanceof Reference){
1678 tableName = "Reference";
1679 }else if (cdmBase instanceof SpecimenOrObservationBase){
1680 tableName = "Specimen";
1681 }else if (cdmBase instanceof Taxon){
1682 tableName = "Taxon";
1683 }else if (cdmBase instanceof Synonym){
1684 tableName = "Synonym";
1685 }else if (cdmBase instanceof TeamOrPersonBase){
1686 tableName = "PersonOrTeam";
1687 }
1688
1689 for (Identifier identifier: identifiers){
1690 if (identifier.getType() == null && identifier.getIdentifier() == null){
1691 state.getResult().addWarning("Please check the identifiers for "
1692 + cdmBaseStr(cdmBase) + " there is an empty identifier");
1693 continue;
1694 }
1695
1696 csvLine = new String[table.getSize()];
1697 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1698
1699 if (tableName != null){
1700 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1701 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1702 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1703 state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1704 }
1705 }
1706 if (cdmBase instanceof Reference ){
1707 Reference ref = (Reference)cdmBase;
1708 if (ref.getDoi() != null){
1709 csvLine = new String[table.getSize()];
1710 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1711 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1712 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1713 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1714 state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1715 }
1716 }
1717
1718 if (cdmBase instanceof TeamOrPersonBase){
1719 TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1720 if (person instanceof Person && ((Person)person).getOrcid() != null){
1721 csvLine = new String[table.getSize()];
1722 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1723 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1724 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1725 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]= ((Person)person).getOrcid().asURI();
1726 state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1727 }
1728 }
1729 }
1730 }
1731 } catch (Exception e) {
1732 state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1733 + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1734 e.printStackTrace();
1735 }
1736 }
1737
1738 private String extractIdentifier(Set<Identifier> identifierSet) {
1739
1740 String identifierString = "";
1741 for (Identifier identifier : identifierSet) {
1742 if (!StringUtils.isBlank(identifierString)) {
1743 identifierString += ", ";
1744 }
1745 identifierString += identifier.getIdentifier();
1746 }
1747 return identifierString;
1748 }
1749
1750 private String extractProtologueURIs(CdmLightExportState state, TaxonName name) {
1751 if (name.getNomenclaturalSource() != null){
1752 Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1753 return extractLinkUris(links.iterator());
1754 }else{
1755 return null;
1756 }
1757 }
1758
1759 private String extractMediaURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1760 Feature feature) {
1761
1762 String mediaUriString = "";
1763 Set<DescriptionElementBase> elements = new HashSet<>();
1764 for (DescriptionBase<?> description : descriptionsSet) {
1765 try {
1766 if (!description.getElements().isEmpty()) {
1767 elements = description.getElements();
1768
1769 for (DescriptionElementBase element : elements) {
1770 Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1771 if (entityFeature.equals(feature)) {
1772 if (!element.getMedia().isEmpty()) {
1773 List<Media> media = element.getMedia();
1774 for (Media mediaElement : media) {
1775 Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1776 mediaUriString = extractMediaUris(it);
1777 }
1778 }
1779 }
1780 }
1781 }
1782 } catch (Exception e) {
1783 state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1784 + cdmBaseStr(description) + ": " + e.getMessage());
1785 }
1786 }
1787 return mediaUriString;
1788 }
1789
1790 private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1791 try {
1792 if (state.getAuthorFromStore(author.getId()) != null) {
1793 return;
1794 }
1795 state.addAuthorToStore(author);
1796 handleIdentifier(state, author);
1797 CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1798 String[] csvLine = new String[table.getSize()];
1799 CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1800 String[] csvLineRel = new String[tableAuthorRel.getSize()];
1801 String[] csvLineMember = new String[table.getSize()];
1802 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1803 csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1804 ? author.getTitleCache() : author.getNomenclaturalTitleCache();
1805 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1806 author = HibernateProxyHelper.deproxy(author);
1807 if (author instanceof Person) {
1808 Person authorPerson = (Person) author;
1809 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1810 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1811 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1812 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1813 } else {
1814 // create an entry in rel table and all members in author table,
1815 // check whether the team members already in author table
1816
1817 Team authorTeam = (Team) author;
1818 int index = 0;
1819 for (Person member : authorTeam.getTeamMembers()) {
1820 csvLineRel = new String[tableAuthorRel.getSize()];
1821 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1822 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1823 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1824 .valueOf(index);
1825 state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1826
1827 if (state.getAuthorFromStore(member.getId()) == null) {
1828 state.addAuthorToStore(member);
1829 csvLineMember = new String[table.getSize()];
1830 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1831 csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1832 .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitleCache();
1833 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1834 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1835 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1836 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1837 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1838 state.getProcessor().put(table, member, csvLineMember);
1839 }
1840 index++;
1841 }
1842 }
1843 state.getProcessor().put(table, author, csvLine);
1844 } catch (Exception e) {
1845 state.getResult().addException(e,
1846 "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1847 }
1848 }
1849
1850 private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1851 try {
1852 Set<NomenclaturalStatus> status = name.getStatus();
1853 if (status.isEmpty()) {
1854 return "";
1855 }
1856 String statusString = "";
1857 for (NomenclaturalStatus nameStatus : status) {
1858 if (nameStatus != null) {
1859 if (abbrev) {
1860 if (nameStatus.getType() != null) {
1861 statusString += nameStatus.getType().getIdInVocabulary();
1862 }
1863 } else {
1864 if (nameStatus.getType() != null) {
1865 statusString += nameStatus.getType().getTitleCache();
1866 }
1867 }
1868 if (!abbrev) {
1869
1870 if (nameStatus.getRuleConsidered() != null
1871 && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1872 statusString += ": " + nameStatus.getRuleConsidered();
1873 }
1874 if (nameStatus.getCitation() != null) {
1875 String shortCitation = OriginalSourceFormatter.INSTANCE.format(nameStatus.getCitation(), null);
1876 statusString += " (" + shortCitation + ")";
1877 }
1878 // if (nameStatus.getCitationMicroReference() != null
1879 // && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1880 // statusString += " " + nameStatus.getCitationMicroReference();
1881 // }
1882 }
1883 statusString += " ";
1884 }
1885 }
1886 return statusString;
1887 } catch (Exception e) {
1888 state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1889 + cdmBaseStr(name) + ": " + e.getMessage());
1890 return "";
1891 }
1892 }
1893
1894 private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, Taxon acceptedTaxon, int sortIndex) {
1895 try {
1896 state.addHomotypicalGroupToStore(group);
1897 CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1898 String[] csvLine = new String[table.getSize()];
1899 csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(sortIndex);
1900 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1901
1902 List<TaxonName> typifiedNames = new ArrayList<>();
1903 if (acceptedTaxon != null){
1904 List<Synonym> synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group);
1905 if (group.equals(acceptedTaxon.getHomotypicGroup())){
1906 typifiedNames.add(acceptedTaxon.getName());
1907 }
1908 synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(CdmBase.deproxy(synonym.getName())));
1909 }
1910
1911
1912 TaxonName firstname = null;
1913 for (TaxonName name: typifiedNames){
1914 Iterator<Taxon> taxa = name.getTaxa().iterator();
1915 while(taxa.hasNext()){
1916 Taxon taxon = taxa.next();
1917 if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1918 firstname = name;
1919 break;
1920 }
1921 }
1922 }
1923
1924 // Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1925 String typifiedNamesString = "";
1926 String typifiedNamesWithSecString = "";
1927 String typifiedNamesWithoutAccepted = "";
1928 String typifiedNamesWithoutAcceptedWithSec = "";
1929 int index = 0;
1930 for (TaxonName name : typifiedNames) {
1931 // Concatenated output string for homotypic group (names and
1932 // citations) + status + some name relations (e.g. “non”)
1933 // TODO: nameRelations, which and how to display
1934 Set<TaxonBase> taxonBases = name.getTaxonBases();
1935 TaxonBase<?> taxonBase;
1936
1937 String sec = "";
1938 String nameString = name.getFullTitleCache();
1939 String doubtful = "";
1940
1941 if (state.getConfig().isAddHTML()){
1942 nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1943 }
1944
1945 Set<NameRelationship> related = name.getNameRelations();
1946 List<NameRelationship> relatedList = new ArrayList<>(related);
1947
1948 Collections.sort(relatedList, (nr1, nr2)-> {
1949 return nr1.getType().compareTo(nr2.getType());});
1950
1951 List<NameRelationship> nonNames = new ArrayList<>();
1952 List<NameRelationship> otherRelationships = new ArrayList<>();
1953
1954 for (NameRelationship rel: relatedList){
1955 //no inverse relations
1956 if (rel.getFromName().equals(name)){
1957 // alle Homonyme und inverse blocking names
1958 if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1959 || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1960 || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1961 || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
1962 || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
1963 ){
1964 nonNames.add(rel);
1965 }else if (!rel.getType().isBasionymRelation()){
1966 otherRelationships.add(rel);
1967 }
1968 }
1969 if (state.getConfig().isShowInverseNameRelationsInHomotypicGroup()) {
1970 if (rel.getToName().equals(name)){
1971 // alle Homonyme und inverse blocking names
1972 // if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1973 // || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1974 // || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1975 // || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
1976 // || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
1977 // ){
1978 // nonNames.add(rel);
1979 // }else if (!rel.getType().isBasionymRelation()){
1980 otherRelationships.add(rel);
1981 // }
1982 }
1983 }
1984 }
1985
1986 String nonRelNames = "";
1987 String relNames = "";
1988
1989 if (nonNames.size() > 0){
1990 nonRelNames += " [";
1991 }
1992 for (NameRelationship relName: nonNames){
1993 String label = "non ";
1994 TaxonName relatedName = null;
1995 if (relName.getFromName().equals(name)){
1996 relatedName = relName.getToName();
1997 if (state.getConfig().isAddHTML()){
1998 nonRelNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
1999 }else{
2000 nonRelNames += label + relatedName.getTitleCache();
2001 }
2002 }
2003 // else{
2004 // label = relName.getType().getInverseLabel() + " ";
2005 // relatedName = relName.getFromName();
2006 // nonRelNames += label + relatedName.getTitleCache() + " ";
2007 // }
2008 }
2009 nonRelNames.trim();
2010 if (nonNames.size() > 0){
2011 nonRelNames = StringUtils.strip(nonRelNames, null);
2012 nonRelNames += "] ";
2013 }
2014
2015 //other relationships
2016 if (otherRelationships.size() > 0){
2017 relNames += " [";
2018 }
2019 for (NameRelationship rel: otherRelationships){
2020 String label = "";
2021 TaxonName relatedName = null;
2022 if (rel.getFromName().equals(name)){
2023 label = rel.getType().getLabel() + " ";
2024 relatedName = rel.getToName();
2025 if (state.getConfig().isAddHTML()){
2026 relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
2027 }else{
2028 relNames += label + relatedName.getTitleCache();
2029 }
2030 }
2031 else {
2032 label = rel.getType().getInverseLabel() + " ";
2033 relatedName = rel.getFromName();
2034 if (state.getConfig().isAddHTML()){
2035 relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
2036 }else{
2037 relNames += label + relatedName.getTitleCache();
2038 }
2039 }
2040 }
2041 relNames.trim();
2042 if (otherRelationships.size() > 0){
2043 relNames = StringUtils.stripEnd(relNames, null);
2044 relNames += "] ";
2045 }
2046
2047
2048 String synonymSign = "";
2049 if (index > 0){
2050 if (name.isInvalid()){
2051 synonymSign = "\u2212 ";
2052 }else{
2053 synonymSign = "\u2261 ";
2054 }
2055 }else{
2056 if (name.isInvalid() ){
2057 synonymSign = "\u2212 ";
2058 }else{
2059 synonymSign = "\u003D ";
2060 }
2061 }
2062 boolean isAccepted = false;
2063
2064 if (taxonBases.size() == 1){
2065 taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
2066
2067 if (taxonBase.getSec() != null){
2068 sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(taxonBase.getSecSource());
2069 }
2070 if (taxonBase.isDoubtful()){
2071 doubtful = "?";
2072 }else{
2073 doubtful = "";
2074 }
2075 if (taxonBase instanceof Synonym){
2076 if (isNotBlank(sec)){
2077 sec = " syn. sec. " + sec + " ";
2078 }else {
2079 sec = "";
2080 }
2081
2082 typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + nonRelNames + relNames;
2083 typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2084 }else{
2085 // sec = "";
2086 if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
2087 isAccepted = true;
2088 }else {
2089 synonymSign = "\u003D ";
2090 }
2091
2092 }
2093 if (taxonBase.getAppendedPhrase() != null){
2094 if (state.getConfig().isAddHTML()){
2095 String taxonString = createNameWithItalics(taxonBase.getTaggedTitle()) ;
2096 taxonString = taxonString.replace("sec "+sec, "");
2097 String nameCacheWithItalics = createNameWithItalics(name.getTaggedName());
2098 nameString = nameString.replace(nameCacheWithItalics, taxonString);
2099 }
2100 }
2101 }else{
2102 //there are names used more than once?
2103 for (TaxonBase<?> tb: taxonBases){
2104 if (tb.getSec() != null){
2105 sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(tb.getSecSource());
2106 }
2107 if (tb.isDoubtful()){
2108 doubtful = "?";
2109 }else{
2110 doubtful = "";
2111 }
2112 if (tb instanceof Synonym ){
2113 Synonym syn = CdmBase.deproxy(tb, Synonym.class);
2114 Taxon acc = syn.getAcceptedTaxon();
2115 if (acc == null || !acc.equals(acceptedTaxon)) {
2116 continue;
2117 }
2118 if (StringUtils.isNotBlank(sec)){
2119 sec = " syn. sec. " + sec + " ";
2120 }else {
2121 sec = "";
2122 }
2123
2124 break;
2125 }else{
2126 sec = "";
2127 Taxon taxon = CdmBase.deproxy(tb, Taxon.class);
2128 if (!(taxon.isProparteSynonym() || taxon.isMisapplication())){
2129 isAccepted = true;
2130 break;
2131 }else {
2132 synonymSign = "\u003D ";
2133 }
2134 }
2135 }
2136 if (!isAccepted){
2137 typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + "; ";
2138 typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec;
2139 typifiedNamesWithoutAcceptedWithSec = typifiedNamesWithoutAcceptedWithSec.trim() + "; ";
2140 }
2141 }
2142 typifiedNamesString += synonymSign + doubtful + nameString + nonRelNames + relNames;
2143 typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2144
2145
2146 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
2147
2148 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
2149
2150 if (typifiedNamesWithoutAccepted != null && firstname != null) {
2151 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
2152 } else {
2153 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = "";
2154 }
2155
2156 if (typifiedNamesWithoutAcceptedWithSec != null && firstname != null) {
2157 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = typifiedNamesWithoutAcceptedWithSec.trim();
2158 } else {
2159 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = "";
2160 }
2161 index++;
2162 }
2163
2164 Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
2165 List<TypeDesignationBase<?>> designationList = new ArrayList<>();
2166 designationList.addAll(typeDesigantionSet);
2167 Collections.sort(designationList, new TypeComparator());
2168
2169 List<TaggedText> list = new ArrayList<>();
2170 if (!designationList.isEmpty()) {
2171 TypeDesignationSetContainer manager = new TypeDesignationSetContainer(group);
2172 list.addAll(new TypeDesignationSetFormatter(true, false, false).toTaggedText(manager));
2173 }
2174 String typeTextDesignations = "";
2175 //The typeDesignationManager does not handle the textual typeDesignations
2176 for (TypeDesignationBase<?> typeDes: designationList) {
2177 if (typeDes instanceof TextualTypeDesignation) {
2178 typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
2179 String typeDesStateRefs = "";
2180 if (typeDes.getDesignationSource() != null ){
2181 typeDesStateRefs = "[";
2182 NamedSource source = typeDes.getDesignationSource();
2183 if (source.getCitation() != null){
2184 typeDesStateRefs += "fide " + OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2185 }
2186 typeDesStateRefs += "]";
2187 }else if (typeDes.getSources() != null && !typeDes.getSources().isEmpty()){
2188 typeDesStateRefs = "[";
2189 for (IdentifiableSource source: typeDes.getSources()) {
2190 if (source.getCitation() != null){
2191 typeDesStateRefs += "fide " +OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2192 }
2193 }
2194
2195 typeDesStateRefs += "]";
2196 }
2197
2198 typeTextDesignations = typeTextDesignations + typeDesStateRefs +"; ";
2199
2200 }else if (typeDes instanceof SpecimenTypeDesignation){
2201 DerivedUnit specimen = ((SpecimenTypeDesignation)typeDes).getTypeSpecimen();
2202 if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
2203 handleSpecimen(state, specimen);
2204 }
2205 }
2206 }
2207 if (typeTextDesignations.equals("; ")) {
2208 typeTextDesignations = "";
2209 }
2210 if (StringUtils.isNotBlank(typeTextDesignations)) {
2211 typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
2212 }
2213 String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
2214
2215 if (StringUtils.isNotBlank(specimenTypeString)) {
2216 if (!specimenTypeString.endsWith(".")) {
2217 specimenTypeString = specimenTypeString + ".";
2218 }
2219 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
2220
2221 } else {
2222 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
2223 }
2224 if (StringUtils.isNotBlank(typeTextDesignations)) {
2225 if (!typeTextDesignations.endsWith(".")) {
2226 typeTextDesignations = typeTextDesignations + ".";
2227 }
2228 csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
2229
2230 } else {
2231 csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
2232 }
2233 state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
2234 } catch (Exception e) {
2235 state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
2236 + cdmBaseStr(group) + ": " + e.getMessage());
2237 }
2238 }
2239
2240 private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup, boolean isSpecimenTypeDesignation) {
2241 StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
2242
2243 for (TaggedText text : list) {
2244 if (text == null || text.getText() == null){
2245 continue; //just in case
2246 }
2247 if ((text.getText().equalsIgnoreCase("Type:") //should not happen anymore
2248 || text.getText().equalsIgnoreCase("Nametype:") //should not happen anymore
2249 || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
2250 // do nothing
2251 }else if (text.getType().equals(TagEnum.reference)) {
2252 homotypicalGroupTypeDesignationString.append(text.getText());
2253 }else if (text.getType().equals(TagEnum.name)){
2254 if (!isSpecimenTypeDesignation){
2255 homotypicalGroupTypeDesignationString
2256 .append("<i>"+text.getText()+"</i> ");
2257 }
2258 }else if (text.getType().equals(TagEnum.typeDesignation) ) {
2259 if(isSpecimenTypeDesignation){
2260 homotypicalGroupTypeDesignationString
2261 .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
2262 }else{
2263 homotypicalGroupTypeDesignationString
2264 .append(text.getText());
2265 }
2266
2267 } else {
2268 homotypicalGroupTypeDesignationString.append(text.getText());
2269 }
2270 }
2271
2272 String typeDesignations = homotypicalGroupTypeDesignationString.toString();
2273 typeDesignations = typeDesignations.trim();
2274
2275 if (typeDesignations.endsWith(";")){
2276 typeDesignations = typeDesignations.substring(0, typeDesignations.length()-1);
2277 }
2278 typeDesignations += ".";
2279 typeDesignations = typeDesignations.replace("..", ".");
2280 typeDesignations = typeDesignations.replace(". .", ".");
2281 typeDesignations = typeDesignations.replace("; \u2261", " \u2261 ");
2282
2283 if (typeDesignations.trim().equals(".")) {
2284 typeDesignations = null;
2285 }
2286
2287 return typeDesignations;
2288 }
2289
2290 private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
2291 try {
2292 String basionymStart = "(";
2293 String basionymEnd = ") ";
2294 String exAuthorSeperator = " ex ";
2295 TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
2296 TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
2297 TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
2298 TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
2299
2300 String combinationAuthorString = "";
2301 if (combinationAuthor != null) {
2302 combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
2303 if (combinationAuthor instanceof Team) {
2304 combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
2305 } else {
2306 Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
2307 combinationAuthorString = createTropicosAuthorString(person);
2308 }
2309 }
2310 String exCombinationAuthorString = "";
2311 if (exCombinationAuthor != null) {
2312 exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
2313 if (exCombinationAuthor instanceof Team) {
2314 exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
2315 } else {
2316 Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
2317 exCombinationAuthorString = createTropicosAuthorString(person);
2318 }
2319 }
2320
2321 String basionymAuthorString = "";
2322 if (basionymAuthor != null) {
2323 basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
2324 if (basionymAuthor instanceof Team) {
2325 basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
2326 } else {
2327 Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
2328 basionymAuthorString = createTropicosAuthorString(person);
2329 }
2330 }
2331
2332 String exBasionymAuthorString = "";
2333
2334 if (exBasionymAuthor != null) {
2335 exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
2336 if (exBasionymAuthor instanceof Team) {
2337 exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
2338
2339 } else {
2340 Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
2341 exBasionymAuthorString = createTropicosAuthorString(person);
2342 }
2343 }
2344 String completeAuthorString = name.getNameCache() + " ";
2345
2346 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2347 || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
2348 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
2349 ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
2350 completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
2351 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2352 || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
2353 completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
2354 ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
2355 completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
2356 : "";
2357
2358 return completeAuthorString;
2359 } catch (Exception e) {
2360 state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
2361 + cdmBaseStr(name) + ": " + e.getMessage());
2362 return null;
2363 }
2364 }
2365
2366 private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
2367 String combinationAuthorString;
2368 Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
2369 Team tempTeam = Team.NewInstance();
2370 for (Person teamMember : team.getTeamMembers()) {
2371 combinationAuthorString = createTropicosAuthorString(teamMember);
2372 Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
2373 tempTeam.addTeamMember(tempPerson);
2374 }
2375 combinationAuthorString = tempTeam.generateTitle();
2376 return combinationAuthorString;
2377 }
2378
2379 private String createTropicosAuthorString(Person teamMember) {
2380 String nomAuthorString = "";
2381 String[] splittedAuthorString = null;
2382 if (teamMember == null) {
2383 return nomAuthorString;
2384 }
2385
2386 if (teamMember.getGivenName() != null) {
2387 String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
2388 splittedAuthorString = givenNameString.split("\\s");
2389 for (String split : splittedAuthorString) {
2390 if (!StringUtils.isBlank(split)) {
2391 nomAuthorString += split.substring(0, 1);
2392 nomAuthorString += ".";
2393 }
2394 }
2395 }
2396 if (teamMember.getFamilyName() != null) {
2397 String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
2398 splittedAuthorString = familyNameString.split("\\s");
2399 for (String split : splittedAuthorString) {
2400 nomAuthorString += " " + split;
2401 }
2402 }
2403 if (isBlank(nomAuthorString.trim())) {
2404 if (teamMember.getTitleCache() != null) {
2405 String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
2406 splittedAuthorString = titleCacheString.split("\\s");
2407 } else {
2408 splittedAuthorString = new String[0];
2409 }
2410
2411 int index = 0;
2412 for (String split : splittedAuthorString) {
2413 if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
2414 nomAuthorString += split;
2415 } else {
2416 nomAuthorString = nomAuthorString + " " + split;
2417 }
2418 index++;
2419 }
2420 }
2421 return nomAuthorString.trim();
2422 }
2423
2424 private void handleReference(CdmLightExportState state, Reference reference) {
2425 try {
2426 state.addReferenceToStore(reference);
2427 CdmLightExportTable table = CdmLightExportTable.REFERENCE;
2428 reference = HibernateProxyHelper.deproxy(reference);
2429
2430 handleIdentifier(state, reference);
2431 String[] csvLine = new String[table.getSize()];
2432 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
2433 // TODO short citations correctly
2434 String shortCitation = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(reference, null); // Should be Author(year) like in Taxon.sec
2435 csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
2436 // TODO get preferred title
2437 csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
2438 ? reference.getTitleCache() : reference.getTitle();
2439 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
2440 ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
2441 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
2442 // TBC
2443 csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
2444 csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
2445 csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
2446 csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
2447 csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
2448 csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
2449 csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
2450 csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
2451 csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
2452 csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
2453 csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
2454 csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
2455
2456 if (reference.getAuthorship() != null) {
2457 csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
2458 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
2459 }
2460
2461 csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
2462 if (reference.getInReference() != null
2463 && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
2464 handleReference(state, reference.getInReference());
2465 }
2466 if (reference.getInstitution() != null) {
2467 csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
2468 }
2469 if (reference.getLsid() != null) {
2470 csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
2471 }
2472 if (reference.getSchool() != null) {
2473 csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
2474 }
2475 if (reference.getUri() != null) {
2476 csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
2477 }
2478 csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
2479
2480 state.getProcessor().put(table, reference, csvLine);
2481 } catch (Exception e) {
2482 state.getResult().addException(e, "An unexpected error occurred when handling reference "
2483 + cdmBaseStr(reference) + ": " + e.getMessage());
2484 }
2485 }
2486
2487 private String createFullAuthorship(Reference reference) {
2488 TeamOrPersonBase<?> authorship = reference.getAuthorship();
2489 String fullAuthorship = "";
2490 if (authorship == null) {
2491 return null;
2492 }
2493 authorship = HibernateProxyHelper.deproxy(authorship);
2494 if (authorship instanceof Person) {
2495 fullAuthorship = ((Person) authorship).getTitleCache();
2496
2497 } else if (authorship instanceof Team) {
2498
2499 Team authorTeam = (Team)authorship;
2500 fullAuthorship = authorTeam.cacheStrategy().getTitleCache(authorTeam);
2501 }
2502 return fullAuthorship;
2503 }
2504
2505 private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
2506 try {
2507 state.addSpecimenToStore(specimen);
2508 CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
2509 String specimenId = getId(state, specimen);
2510 String[] csvLine = new String[table.getSize()];
2511
2512 /*
2513 * SpecimenCitation = “El Salvador, Municipio La Libertad, San
2514 * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
2515 * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
2516 * HerbariumCode
2517 */
2518
2519 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
2520 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
2521 Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
2522 if (fieldUnits.size() == 1) {
2523 Iterator<FieldUnit> iterator = fieldUnits.iterator();
2524 if (iterator.hasNext()){
2525 FieldUnit fieldUnit = iterator.next();
2526 csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
2527 }
2528 }
2529 if (specimen.isInstanceOf(DerivedUnit.class)){
2530 DerivedUnit derivedUnit = (DerivedUnit) specimen;
2531 if (!StringUtils.isBlank(derivedUnit.getBarcode())){
2532 csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
2533 }
2534 if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
2535 csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
2536 }
2537 if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
2538 csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
2539 }
2540 }
2541
2542 csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
2543 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
2544 specimen.getDescriptions(), Feature.IMAGE());
2545 if (specimen instanceof DerivedUnit) {
2546 DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(specimen, DerivedUnit.class);
2547 if (derivedUnit.getCollection() != null) {
2548 csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
2549 .getCode();
2550 }
2551
2552 if (specimen instanceof MediaSpecimen) {
2553 MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
2554 Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
2555 String mediaUris = extractMediaUris(it);
2556 csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
2557 }
2558
2559 if (derivedUnit.getDerivedFrom() == null) {
2560 state.getResult().addWarning("The specimen with uuid " + specimen.getUuid()
2561 + " does not have a field unit.");
2562 } else {
2563 for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
2564 // TODO: What to do if there are more then one
2565 // FieldUnit??
2566 if (original instanceof FieldUnit) {
2567 FieldUnit fieldUnit = (FieldUnit) original;
2568 csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
2569
2570 GatheringEvent gathering = fieldUnit.getGatheringEvent();
2571 if (gathering != null) {
2572 if (gathering.getLocality() != null) {
2573 csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
2574 .getText();
2575 }
2576 if (gathering.getCountry() != null) {
2577 csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
2578 .getLabel();
2579 }
2580 csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2581 state, gathering, fieldUnit);
2582
2583 if (gathering.getGatheringDate() != null) {
2584 csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2585 .getGatheringDate().toString();
2586 }
2587 if (!gathering.getCollectingAreas().isEmpty()) {
2588 int index = 0;
2589 csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2590 for (NamedArea area : gathering.getCollectingAreas()) {
2591 if (index == 0) {
2592 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2593 .getLevel().getLabel():"";
2594 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2595 }
2596 if (index == 1) {
2597 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2598 .getLevel().getLabel():"";
2599 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2600 }
2601 if (index == 2) {
2602 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2603 .getLevel().getLabel():"";
2604 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2605 }
2606 if (index == 3) {
2607 csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2608 break;
2609 }
2610 index++;
2611 }
2612 }
2613 }
2614 }
2615 }
2616 }
2617 }
2618
2619 state.getProcessor().put(table, specimen, csvLine);
2620 } catch (Exception e) {
2621 state.getResult().addException(e, "An unexpected error occurred when handling specimen "
2622 + cdmBaseStr(specimen) + ": " + e.getMessage());
2623 }
2624 }
2625
2626 private String extractMediaUris(Iterator<MediaRepresentation> it) {
2627
2628 String mediaUriString = "";
2629 boolean first = true;
2630 while (it.hasNext()) {
2631 MediaRepresentation rep = it.next();
2632 List<MediaRepresentationPart> parts = rep.getParts();
2633 for (MediaRepresentationPart part : parts) {
2634 if (first) {
2635 if (part.getUri() != null) {
2636 mediaUriString += part.getUri().toString();
2637 first = false;
2638 }
2639 } else {
2640 if (part.getUri() != null) {
2641 mediaUriString += ", " + part.getUri().toString();
2642 }
2643 }
2644 }
2645 }
2646
2647 return mediaUriString;
2648 }
2649
2650 private String extractLinkUris(Iterator<ExternalLink> it) {
2651
2652 String linkUriString = "";
2653 boolean first = true;
2654 while (it.hasNext()) {
2655 ExternalLink link = it.next();
2656 if (first) {
2657 if (link.getUri() != null) {
2658 linkUriString += link.getUri().toString();
2659 first = false;
2660 }
2661 } else {
2662 if (link.getUri() != null) {
2663 linkUriString += ", " + link.getUri().toString();
2664 }
2665 }
2666 }
2667 return linkUriString;
2668 }
2669
2670 private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
2671 try {
2672 String collectorString = "";
2673 AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
2674 if (gathering.getCollector() != null) {
2675 if (collectorA instanceof TeamOrPersonBase && state.getConfig().isHighLightPrimaryCollector()) {
2676
2677 Person primaryCollector = fieldUnit.getPrimaryCollector();
2678 if (collectorA instanceof Team) {
2679 Team collectorTeam = (Team) collectorA;
2680 boolean isFirst = true;
2681 for (Person member : collectorTeam.getTeamMembers()) {
2682 if (!isFirst) {
2683 collectorString += "; ";
2684 }
2685 if (member.equals(primaryCollector)) {
2686 // highlight
2687 collectorString += "<b>" + member.getTitleCache() + "</b>";
2688 } else {
2689 collectorString += member.getTitleCache();
2690 }
2691 }
2692 }
2693 } else {
2694 collectorString = collectorA.getTitleCache();
2695 }
2696 }
2697 return collectorString;
2698 } catch (Exception e) {
2699 state.getResult().addException(e, "An unexpected error occurred when creating collector string for "
2700 + cdmBaseStr(fieldUnit) + ": " + e.getMessage());
2701 return "";
2702 }
2703 }
2704
2705 /**
2706 * Returns a string representation of the {@link CdmBase cdmBase} object for
2707 * result messages.
2708 */
2709 private String cdmBaseStr(CdmBase cdmBase) {
2710 if (cdmBase == null) {
2711 return "-no object available-";
2712 } else {
2713 return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
2714 }
2715 }
2716
2717 @Override
2718 protected boolean doCheck(CdmLightExportState state) {
2719 return false;
2720 }
2721
2722 @Override
2723 protected boolean isIgnore(CdmLightExportState state) {
2724 return false;
2725 }
2726 }