cleanup
[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)] = createCollatation(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)] = createCollatation(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
1388 Integer seqNumber = typifiedNames.indexOf(name);
1389 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
1390 state.getProcessor().put(table, name, csvLine);
1391 handleNameRelationships(state, name);
1392
1393 } catch (Exception e) {
1394 state.getResult().addException(e,
1395 "An unexpected error occurred when handling the name " + cdmBaseStr(name) + ": " + name.getTitleCache() + ": " + e.getMessage());
1396
1397 e.printStackTrace();
1398 }
1399 }
1400
1401 private void handleSpecimenType_(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1402 if (specimenType.getTypeSpecimen() != null){
1403 DerivedUnit specimen = specimenType.getTypeSpecimen();
1404 if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1405 handleSpecimen(state, specimen);
1406 }
1407 }
1408 CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1409 String[] csvLine = new String[table.getSize()];
1410 //TYPE_ID, SPECIMEN_FK, TYPE_VERBATIM_CITATION, TYPE_STATUS, TYPE_DESIGNATED_BY_STRING, TYPE_DESIGNATED_BY_REF_FK};
1411 //Specimen_Fk und den Typusangaben (Art des Typus [holo, lecto, etc.], Quelle, Designation-Quelle, +
1412 Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1413 for (TaxonName name: typifiedNames){
1414 csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1415 csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
1416 csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1417 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1418 if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1419 String sourceString = "";
1420 int index = 0;
1421 for (IdentifiableSource source: specimenType.getSources()){
1422 if (source.getCitation()!= null){
1423 sourceString = sourceString.concat(source.getCitation().getCitation());
1424 }
1425 index++;
1426 if (index != specimenType.getSources().size()){
1427 sourceString.concat(", ");
1428 }
1429 }
1430 csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1431 }
1432 if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1433 handleReference(state, specimenType.getDesignationSource().getCitation());
1434 csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1435 }
1436
1437 state.getProcessor().put(table, specimenType, csvLine);
1438 }
1439 }
1440
1441
1442 /**
1443 * @param specimenType
1444 */
1445 private void handleSpecimenType(CdmLightExportState state, SpecimenTypeDesignation specimenType) {
1446 if (specimenType.getTypeSpecimen() != null){
1447 DerivedUnit specimen = specimenType.getTypeSpecimen();
1448 if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
1449 handleSpecimen(state, specimen);
1450 }
1451 }
1452 CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1453 String[] csvLine = new String[table.getSize()];
1454
1455 csvLine[table.getIndex(CdmLightExportTable.TYPE_STATUS)] = specimenType.getTypeStatus() != null? specimenType.getTypeStatus().getDescription(): "";
1456 csvLine[table.getIndex(CdmLightExportTable.TYPE_ID)] = getId(state, specimenType);
1457 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1458 if (specimenType.getSources() != null && !specimenType.getSources().isEmpty()){
1459 String sourceString = "";
1460 int index = 0;
1461 List<IdentifiableSource> sources = new ArrayList<>(specimenType.getSources());
1462 Comparator<IdentifiableSource> compareByYear = new Comparator<IdentifiableSource>() {
1463 @Override
1464 public int compare(IdentifiableSource o1, IdentifiableSource o2) {
1465 if (o1 == o2){
1466 return 0;
1467 }
1468 if (o1.getCitation() == null && o2.getCitation() != null){
1469 return -1;
1470 }
1471 if (o2.getCitation() == null && o1.getCitation() != null){
1472 return 1;
1473 }
1474 if (o1.getCitation().equals(o2.getCitation())){
1475 return 0;
1476 }
1477 if (o1.getCitation().getDatePublished() == null && o2.getCitation().getDatePublished() != null){
1478 return -1;
1479 }
1480 if (o1.getCitation().getDatePublished() != null && o2.getCitation().getDatePublished() == null){
1481 return 1;
1482 }
1483 if (o1.getCitation().getDatePublished().getYear() == null && o2.getCitation().getDatePublished().getYear() != null){
1484 return -1;
1485 }
1486 if (o1.getCitation().getDatePublished().getYear() != null && o2.getCitation().getDatePublished().getYear() == null){
1487 return 1;
1488 }
1489 return o1.getCitation().getDatePublished().getYear().compareTo(o2.getCitation().getDatePublished().getYear());
1490 }
1491 };
1492 Collections.sort(sources, compareByYear);
1493 for (IdentifiableSource source: sources){
1494 if (source.getCitation()!= null){
1495 sourceString = sourceString.concat(source.getCitation().getCitation());
1496 handleReference(state, source.getCitation());
1497 }
1498 index++;
1499 if (index <= specimenType.getSources().size()){
1500 sourceString = sourceString.concat("; ");
1501 }
1502 }
1503
1504 csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_STRING)] = sourceString;
1505 if (sources.get(0).getCitation() != null ){
1506 csvLine[table.getIndex(CdmLightExportTable.TYPE_INFORMATION_REF_FK)] = getId(state, sources.get(0).getCitation());
1507 }
1508 }
1509 if (specimenType.getDesignationSource() != null && specimenType.getDesignationSource().getCitation() != null && !state.getReferenceStore().contains(specimenType.getDesignationSource().getCitation().getUuid())){
1510 handleReference(state, specimenType.getDesignationSource().getCitation());
1511 csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = specimenType.getDesignationSource() != null ? getId(state, specimenType.getDesignationSource().getCitation()): "";
1512 }
1513
1514
1515 Set<TaxonName> typifiedNames = specimenType.getTypifiedNames();
1516
1517 if (typifiedNames.size() > 1){
1518 state.getResult().addWarning("Please check the specimen type "
1519 + cdmBaseStr(specimenType) + " there are more then one typified name.");
1520 }
1521 if (typifiedNames.iterator().hasNext()){
1522 TaxonName name = typifiedNames.iterator().next();
1523 csvLine[table.getIndex(CdmLightExportTable.TYPIFIED_NAME_FK)] = getId(state, name);
1524 }
1525 state.getProcessor().put(table, specimenType, csvLine);
1526 }
1527
1528 private String createNameWithItalics(List<TaggedText> taggedName) {
1529
1530 String fullTitleWithHtml = "";
1531 for (TaggedText taggedText: taggedName){
1532 if (taggedText.getType().equals(TagEnum.name)){
1533 fullTitleWithHtml += "<i>" + taggedText.getText() + "</i> ";
1534 }else if (taggedText.getType().equals(TagEnum.separator)){
1535 fullTitleWithHtml = fullTitleWithHtml.trim() + taggedText.getText() ;
1536 }else{
1537 fullTitleWithHtml += taggedText.getText() + " ";
1538 }
1539 }
1540 return fullTitleWithHtml;
1541 }
1542
1543 private void handleNameRelationships(CdmLightExportState state, TaxonName name) {
1544 Set<NameRelationship> rels = name.getRelationsFromThisName();
1545 CdmLightExportTable table = CdmLightExportTable.NAME_RELATIONSHIP;
1546 String[] csvLine = new String[table.getSize()];
1547
1548 for (NameRelationship rel : rels) {
1549 NameRelationshipType type = rel.getType();
1550 TaxonName name2 = rel.getToName();
1551 name2 = HibernateProxyHelper.deproxy(name2, TaxonName.class);
1552 if (!state.getNameStore().containsKey(name2.getId())) {
1553 handleName(state, name2, null);
1554 }
1555 csvLine = new String[table.getSize()];
1556 csvLine[table.getIndex(CdmLightExportTable.NAME_REL_TYPE)] = type.getLabel();
1557 csvLine[table.getIndex(CdmLightExportTable.NAME1_FK)] = getId(state, name);
1558 csvLine[table.getIndex(CdmLightExportTable.NAME2_FK)] = getId(state, name2);
1559 state.getProcessor().put(table, rel.getUuid().toString(), csvLine);
1560 }
1561
1562 rels = name.getRelationsToThisName();
1563
1564 csvLine = new String[table.getSize()];
1565
1566 for (NameRelationship rel : rels) {
1567 TaxonName name2 = rel.getFromName();
1568 name2 = HibernateProxyHelper.deproxy(name2);
1569 if (!state.getNameStore().containsKey(name2.getId())) {
1570 handleName(state, name2, null);
1571 }
1572 }
1573 }
1574
1575 private String createCollatation(TaxonName name) {
1576 String collation = "";
1577 if (name.getNomenclaturalReference() != null) {
1578 Reference ref = name.getNomenclaturalReference();
1579 collation = getVolume(ref);
1580 }
1581 if (name.getNomenclaturalMicroReference() != null) {
1582 if (!StringUtils.isBlank(collation)) {
1583 collation += ":";
1584 }
1585 collation += name.getNomenclaturalMicroReference();
1586 }
1587
1588 return collation;
1589 }
1590
1591 private String getVolume(Reference reference) {
1592 if (reference.getVolume() != null) {
1593 return reference.getVolume();
1594 } else if (reference.getInReference() != null) {
1595 if (reference.getInReference().getVolume() != null) {
1596 return reference.getInReference().getVolume();
1597 }
1598 }
1599 return null;
1600 }
1601
1602 private void handleIdentifier(CdmLightExportState state, CdmBase cdmBase) {
1603 CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1604 String[] csvLine;
1605 try {
1606 if (cdmBase instanceof TaxonName){
1607 TaxonName name = (TaxonName)cdmBase;
1608
1609 try{
1610 List<Identifier> identifiers = name.getIdentifiers();
1611
1612 //first check which kind of identifiers are available and then sort and create table entries
1613 Map<IdentifierType, Set<Identifier>> identifierTypes = new HashMap<>();
1614 for (Identifier identifier: identifiers){
1615 IdentifierType type = identifier.getType();
1616 if (identifierTypes.containsKey(type)){
1617 identifierTypes.get(type).add(identifier);
1618 }else{
1619 Set<Identifier> tempList = new HashSet<>();
1620 tempList.add(identifier);
1621 identifierTypes.put(type, tempList);
1622 }
1623 }
1624
1625 for (IdentifierType type:identifierTypes.keySet()){
1626 Set<Identifier> identifiersByType = identifierTypes.get(type);
1627 csvLine = new String[table.getSize()];
1628 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1629 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1630 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = type.getLabel();
1631 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1632 identifiersByType);
1633 state.getProcessor().put(table, name.getUuid() + ", " + type.getLabel(), csvLine);
1634 }
1635
1636
1637 // Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1638 // Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1639 // Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1640 // if (!IPNIidentifiers.isEmpty()) {
1641 // csvLine = new String[table.getSize()];
1642 // csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1643 // csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1644 // csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1645 // csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1646 // IPNIidentifiers);
1647 // state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1648 // }
1649 // if (!tropicosIdentifiers.isEmpty()) {
1650 // csvLine = new String[table.getSize()];
1651 // csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1652 // csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1653 // csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
1654 // csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1655 // tropicosIdentifiers);
1656 // state.getProcessor().put(table, name.getUuid() + ", " + IPNI_NAME_IDENTIFIER, csvLine);
1657 // }
1658 // if (!WFOIdentifiers.isEmpty()) {
1659 // csvLine = new String[table.getSize()];
1660 // csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, name);
1661 // csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = "ScientificName";
1662 // csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1663 // csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = extractIdentifier(
1664 // WFOIdentifiers);
1665 // state.getProcessor().put(table, name.getUuid() + ", " + WFO_NAME_IDENTIFIER, csvLine);
1666 // }
1667 }catch(Exception e){
1668 state.getResult().addWarning("Please check the identifiers for "
1669 + cdmBaseStr(cdmBase) + " maybe there is an empty identifier");
1670
1671
1672 }
1673 }else{
1674 if (cdmBase instanceof IdentifiableEntity){
1675 IdentifiableEntity<?> identifiableEntity = (IdentifiableEntity<?>) cdmBase;
1676 List<Identifier> identifiers = identifiableEntity.getIdentifiers();
1677 String tableName = null;
1678 if (cdmBase instanceof Reference){
1679 tableName = "Reference";
1680 }else if (cdmBase instanceof SpecimenOrObservationBase){
1681 tableName = "Specimen";
1682 }else if (cdmBase instanceof Taxon){
1683 tableName = "Taxon";
1684 }else if (cdmBase instanceof Synonym){
1685 tableName = "Synonym";
1686 }else if (cdmBase instanceof TeamOrPersonBase){
1687 tableName = "PersonOrTeam";
1688 }
1689
1690 for (Identifier identifier: identifiers){
1691 if (identifier.getType() == null && identifier.getIdentifier() == null){
1692 state.getResult().addWarning("Please check the identifiers for "
1693 + cdmBaseStr(cdmBase) + " there is an empty identifier");
1694 continue;
1695 }
1696
1697 csvLine = new String[table.getSize()];
1698 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1699
1700 if (tableName != null){
1701 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1702 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = identifier.getType() != null? identifier.getType().getLabel():null;
1703 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = identifier.getIdentifier();
1704 state.getProcessor().put(table, cdmBase.getUuid() + (identifier.getType() != null? identifier.getType().getLabel():null), csvLine);
1705 }
1706 }
1707 if (cdmBase instanceof Reference ){
1708 Reference ref = (Reference)cdmBase;
1709 if (ref.getDoi() != null){
1710 csvLine = new String[table.getSize()];
1711 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1712 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1713 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "DOI";
1714 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)] = ref.getDoiString();
1715 state.getProcessor().put(table, cdmBase.getUuid() + "DOI", csvLine);
1716 }
1717 }
1718
1719 if (cdmBase instanceof TeamOrPersonBase){
1720 TeamOrPersonBase<?> person= HibernateProxyHelper.deproxy(cdmBase, TeamOrPersonBase.class);
1721 if (person instanceof Person && ((Person)person).getOrcid() != null){
1722 csvLine = new String[table.getSize()];
1723 csvLine[table.getIndex(CdmLightExportTable.FK)] = getId(state, cdmBase);
1724 csvLine[table.getIndex(CdmLightExportTable.REF_TABLE)] = tableName;
1725 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = "ORCID";
1726 csvLine[table.getIndex(CdmLightExportTable.EXTERNAL_NAME_IDENTIFIER)]= ((Person)person).getOrcid().asURI();
1727 state.getProcessor().put(table, cdmBase.getUuid() + "ORCID", csvLine);
1728 }
1729 }
1730 }
1731 }
1732 } catch (Exception e) {
1733 state.getResult().addException(e, "An unexpected error occurred when handling identifiers for "
1734 + cdmBaseStr(cdmBase) + ": " + e.getMessage());
1735 e.printStackTrace();
1736 }
1737 }
1738
1739 private String extractIdentifier(Set<Identifier> identifierSet) {
1740
1741 String identifierString = "";
1742 for (Identifier identifier : identifierSet) {
1743 if (!StringUtils.isBlank(identifierString)) {
1744 identifierString += ", ";
1745 }
1746 identifierString += identifier.getIdentifier();
1747 }
1748 return identifierString;
1749 }
1750
1751 private String extractProtologueURIs(CdmLightExportState state, TaxonName name) {
1752 if (name.getNomenclaturalSource() != null){
1753 Set<ExternalLink> links = name.getNomenclaturalSource().getLinks();
1754 return extractLinkUris(links.iterator());
1755 }else{
1756 return null;
1757 }
1758 }
1759
1760 private String extractMediaURIs(CdmLightExportState state, Set<? extends DescriptionBase<?>> descriptionsSet,
1761 Feature feature) {
1762
1763 String mediaUriString = "";
1764 Set<DescriptionElementBase> elements = new HashSet<>();
1765 for (DescriptionBase<?> description : descriptionsSet) {
1766 try {
1767 if (!description.getElements().isEmpty()) {
1768 elements = description.getElements();
1769
1770 for (DescriptionElementBase element : elements) {
1771 Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1772 if (entityFeature.equals(feature)) {
1773 if (!element.getMedia().isEmpty()) {
1774 List<Media> media = element.getMedia();
1775 for (Media mediaElement : media) {
1776 Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1777 mediaUriString = extractMediaUris(it);
1778 }
1779 }
1780 }
1781 }
1782 }
1783 } catch (Exception e) {
1784 state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for "
1785 + cdmBaseStr(description) + ": " + e.getMessage());
1786 }
1787 }
1788 return mediaUriString;
1789 }
1790
1791 private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1792 try {
1793 if (state.getAuthorFromStore(author.getId()) != null) {
1794 return;
1795 }
1796 state.addAuthorToStore(author);
1797 handleIdentifier(state, author);
1798 CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1799 String[] csvLine = new String[table.getSize()];
1800 CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1801 String[] csvLineRel = new String[tableAuthorRel.getSize()];
1802 String[] csvLineMember = new String[table.getSize()];
1803 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1804 csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.isProtectedTitleCache()
1805 ? author.getTitleCache() : author.getNomenclaturalTitleCache();
1806 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1807 author = HibernateProxyHelper.deproxy(author);
1808 if (author instanceof Person) {
1809 Person authorPerson = (Person) author;
1810 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1811 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1812 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1813 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1814 } else {
1815 // create an entry in rel table and all members in author table,
1816 // check whether the team members already in author table
1817
1818 Team authorTeam = (Team) author;
1819 int index = 0;
1820 for (Person member : authorTeam.getTeamMembers()) {
1821 csvLineRel = new String[tableAuthorRel.getSize()];
1822 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1823 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1824 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String
1825 .valueOf(index);
1826 state.getProcessor().put(tableAuthorRel, authorTeam.getId() + ":" + member.getId(), csvLineRel);
1827
1828 if (state.getAuthorFromStore(member.getId()) == null) {
1829 state.addAuthorToStore(member);
1830 csvLineMember = new String[table.getSize()];
1831 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1832 csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member
1833 .isProtectedTitleCache() ? member.getTitleCache() : member.getNomenclaturalTitleCache();
1834 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1835 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1836 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1837 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1838 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1839 state.getProcessor().put(table, member, csvLineMember);
1840 }
1841 index++;
1842 }
1843 }
1844 state.getProcessor().put(table, author, csvLine);
1845 } catch (Exception e) {
1846 state.getResult().addException(e,
1847 "An unexpected error occurred when handling author " + cdmBaseStr(author) + ": " + e.getMessage());
1848 }
1849 }
1850
1851 private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1852 try {
1853 Set<NomenclaturalStatus> status = name.getStatus();
1854 if (status.isEmpty()) {
1855 return "";
1856 }
1857 String statusString = "";
1858 for (NomenclaturalStatus nameStatus : status) {
1859 if (nameStatus != null) {
1860 if (abbrev) {
1861 if (nameStatus.getType() != null) {
1862 statusString += nameStatus.getType().getIdInVocabulary();
1863 }
1864 } else {
1865 if (nameStatus.getType() != null) {
1866 statusString += nameStatus.getType().getTitleCache();
1867 }
1868 }
1869 if (!abbrev) {
1870
1871 if (nameStatus.getRuleConsidered() != null
1872 && !StringUtils.isBlank(nameStatus.getRuleConsidered())) {
1873 statusString += ": " + nameStatus.getRuleConsidered();
1874 }
1875 if (nameStatus.getCitation() != null) {
1876 String shortCitation = OriginalSourceFormatter.INSTANCE.format(nameStatus.getCitation(), null);
1877 statusString += " (" + shortCitation + ")";
1878 }
1879 // if (nameStatus.getCitationMicroReference() != null
1880 // && !StringUtils.isBlank(nameStatus.getCitationMicroReference())) {
1881 // statusString += " " + nameStatus.getCitationMicroReference();
1882 // }
1883 }
1884 statusString += " ";
1885 }
1886 }
1887 return statusString;
1888 } catch (Exception e) {
1889 state.getResult().addException(e, "An unexpected error occurred when extracting status string for "
1890 + cdmBaseStr(name) + ": " + e.getMessage());
1891 return "";
1892 }
1893 }
1894
1895 private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group, Taxon acceptedTaxon, int sortIndex) {
1896 try {
1897 state.addHomotypicalGroupToStore(group);
1898 CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1899 String[] csvLine = new String[table.getSize()];
1900 csvLine[table.getIndex(CdmLightExportTable.SORT_INDEX)] = String.valueOf(sortIndex);
1901 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1902
1903 List<TaxonName> typifiedNames = new ArrayList<>();
1904 if (acceptedTaxon != null){
1905 List<Synonym> synonymsInGroup = acceptedTaxon.getSynonymsInGroup(group);
1906 if (group.equals(acceptedTaxon.getHomotypicGroup())){
1907 typifiedNames.add(acceptedTaxon.getName());
1908 }
1909 synonymsInGroup.stream().forEach(synonym -> typifiedNames.add(CdmBase.deproxy(synonym.getName())));
1910 }
1911
1912
1913 TaxonName firstname = null;
1914 for (TaxonName name: typifiedNames){
1915 Iterator<Taxon> taxa = name.getTaxa().iterator();
1916 while(taxa.hasNext()){
1917 Taxon taxon = taxa.next();
1918 if(!(taxon.isMisapplication() || taxon.isProparteSynonym())){
1919 firstname = name;
1920 break;
1921 }
1922 }
1923 }
1924
1925 // Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(firstname, true));
1926 String typifiedNamesString = "";
1927 String typifiedNamesWithSecString = "";
1928 String typifiedNamesWithoutAccepted = "";
1929 String typifiedNamesWithoutAcceptedWithSec = "";
1930 int index = 0;
1931 for (TaxonName name : typifiedNames) {
1932 // Concatenated output string for homotypic group (names and
1933 // citations) + status + some name relations (e.g. “non”)
1934 // TODO: nameRelations, which and how to display
1935 Set<TaxonBase> taxonBases = name.getTaxonBases();
1936 TaxonBase<?> taxonBase;
1937
1938 String sec = "";
1939 String nameString = name.getFullTitleCache();
1940 String doubtful = "";
1941
1942 if (state.getConfig().isAddHTML()){
1943 nameString = createNameWithItalics(name.getTaggedFullTitle()) ;
1944 }
1945
1946 Set<NameRelationship> related = name.getNameRelations();
1947 List<NameRelationship> relatedList = new ArrayList<>(related);
1948
1949 Collections.sort(relatedList, (nr1, nr2)-> {
1950 return nr1.getType().compareTo(nr2.getType());});
1951
1952 List<NameRelationship> nonNames = new ArrayList<>();
1953 List<NameRelationship> otherRelationships = new ArrayList<>();
1954
1955 for (NameRelationship rel: relatedList){
1956 //no inverse relations
1957 if (rel.getFromName().equals(name)){
1958 // alle Homonyme und inverse blocking names
1959 if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1960 || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1961 || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1962 || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
1963 || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
1964 ){
1965 nonNames.add(rel);
1966 }else if (!rel.getType().isBasionymRelation()){
1967 otherRelationships.add(rel);
1968 }
1969 }
1970 if (state.getConfig().isShowInverseNameRelationsInHomotypicGroup()) {
1971 if (rel.getToName().equals(name)){
1972 // alle Homonyme und inverse blocking names
1973 // if (rel.getType().equals(NameRelationshipType.LATER_HOMONYM())
1974 // || rel.getType().equals(NameRelationshipType.TREATED_AS_LATER_HOMONYM())
1975 // || (rel.getType().equals(NameRelationshipType.BLOCKING_NAME_FOR()))
1976 // || (rel.getType().equals(NameRelationshipType.UNSPECIFIC_NON()))
1977 // || (rel.getType().equals(NameRelationshipType.AVOIDS_HOMONYM_OF()))
1978 // ){
1979 // nonNames.add(rel);
1980 // }else if (!rel.getType().isBasionymRelation()){
1981 otherRelationships.add(rel);
1982 // }
1983 }
1984 }
1985 }
1986
1987 String nonRelNames = "";
1988 String relNames = "";
1989
1990 if (nonNames.size() > 0){
1991 nonRelNames += " [";
1992 }
1993 for (NameRelationship relName: nonNames){
1994 String label = "non ";
1995 TaxonName relatedName = null;
1996 if (relName.getFromName().equals(name)){
1997 relatedName = relName.getToName();
1998 if (state.getConfig().isAddHTML()){
1999 nonRelNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
2000 }else{
2001 nonRelNames += label + relatedName.getTitleCache();
2002 }
2003 }
2004 // else{
2005 // label = relName.getType().getInverseLabel() + " ";
2006 // relatedName = relName.getFromName();
2007 // nonRelNames += label + relatedName.getTitleCache() + " ";
2008 // }
2009 }
2010 nonRelNames.trim();
2011 if (nonNames.size() > 0){
2012 nonRelNames = StringUtils.strip(nonRelNames, null);
2013 nonRelNames += "] ";
2014 }
2015
2016 //other relationships
2017 if (otherRelationships.size() > 0){
2018 relNames += " [";
2019 }
2020 for (NameRelationship rel: otherRelationships){
2021 String label = "";
2022 TaxonName relatedName = null;
2023 if (rel.getFromName().equals(name)){
2024 label = rel.getType().getLabel() + " ";
2025 relatedName = rel.getToName();
2026 if (state.getConfig().isAddHTML()){
2027 relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
2028 }else{
2029 relNames += label + relatedName.getTitleCache();
2030 }
2031 }
2032 else {
2033 label = rel.getType().getInverseLabel() + " ";
2034 relatedName = rel.getFromName();
2035 if (state.getConfig().isAddHTML()){
2036 relNames += label + createNameWithItalics(relatedName.getTaggedName())+ " ";
2037 }else{
2038 relNames += label + relatedName.getTitleCache();
2039 }
2040 }
2041 }
2042 relNames.trim();
2043 if (otherRelationships.size() > 0){
2044 relNames = StringUtils.stripEnd(relNames, null);
2045 relNames += "] ";
2046 }
2047
2048
2049 String synonymSign = "";
2050 if (index > 0){
2051 if (name.isInvalid()){
2052 synonymSign = "\u2212 ";
2053 }else{
2054 synonymSign = "\u2261 ";
2055 }
2056 }else{
2057 if (name.isInvalid() ){
2058 synonymSign = "\u2212 ";
2059 }else{
2060 synonymSign = "\u003D ";
2061 }
2062 }
2063 boolean isAccepted = false;
2064
2065 if (taxonBases.size() == 1){
2066 taxonBase = HibernateProxyHelper.deproxy(taxonBases.iterator().next());
2067
2068 if (taxonBase.getSec() != null){
2069 sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(taxonBase.getSecSource());
2070 }
2071 if (taxonBase.isDoubtful()){
2072 doubtful = "?";
2073 }else{
2074 doubtful = "";
2075 }
2076 if (taxonBase instanceof Synonym){
2077 if (isNotBlank(sec)){
2078 sec = " syn. sec. " + sec + " ";
2079 }else {
2080 sec = "";
2081 }
2082
2083 typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + nonRelNames + relNames;
2084 typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2085 }else{
2086 // sec = "";
2087 if (!(((Taxon)taxonBase).isProparteSynonym() || ((Taxon)taxonBase).isMisapplication())){
2088 isAccepted = true;
2089 }else {
2090 synonymSign = "\u003D ";
2091 }
2092
2093 }
2094 if (taxonBase.getAppendedPhrase() != null){
2095 if (state.getConfig().isAddHTML()){
2096 String taxonString = createNameWithItalics(taxonBase.getTaggedTitle()) ;
2097 taxonString = taxonString.replace("sec "+sec, "");
2098 String nameCacheWithItalics = createNameWithItalics(name.getTaggedName());
2099 nameString = nameString.replace(nameCacheWithItalics, taxonString);
2100 }
2101 }
2102 }else{
2103 //there are names used more than once?
2104 for (TaxonBase<?> tb: taxonBases){
2105 if (tb.getSec() != null){
2106 sec = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(tb.getSecSource());
2107 }
2108 if (tb.isDoubtful()){
2109 doubtful = "?";
2110 }else{
2111 doubtful = "";
2112 }
2113 if (tb instanceof Synonym ){
2114 if (!((Synonym)tb).getAcceptedTaxon().equals(acceptedTaxon)) {
2115 continue;
2116 }
2117 if (StringUtils.isNotBlank(sec)){
2118 sec = " syn. sec. " + sec + " ";
2119 }else {
2120 sec = "";
2121 }
2122
2123 break;
2124 }else{
2125 sec = "";
2126 if (!(((Taxon)tb).isProparteSynonym() || ((Taxon)tb).isMisapplication())){
2127 isAccepted = true;
2128 break;
2129 }else {
2130 synonymSign = "\u003D ";
2131 }
2132 }
2133 }
2134 if (!isAccepted){
2135 typifiedNamesWithoutAccepted += synonymSign + doubtful + nameString + "; ";
2136 typifiedNamesWithoutAcceptedWithSec += synonymSign + doubtful + nameString + sec;
2137 typifiedNamesWithoutAcceptedWithSec = typifiedNamesWithoutAcceptedWithSec.trim() + "; ";
2138 }
2139 }
2140 typifiedNamesString += synonymSign + doubtful + nameString + nonRelNames + relNames;
2141 typifiedNamesWithSecString += synonymSign + doubtful + nameString + sec + nonRelNames + relNames;
2142
2143
2144 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
2145
2146 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITH_SEC_STRING)] = typifiedNamesWithSecString.trim();
2147
2148 if (typifiedNamesWithoutAccepted != null && firstname != null) {
2149 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = typifiedNamesWithoutAccepted.trim();
2150 } else {
2151 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTED)] = "";
2152 }
2153
2154 if (typifiedNamesWithoutAcceptedWithSec != null && firstname != null) {
2155 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = typifiedNamesWithoutAcceptedWithSec.trim();
2156 } else {
2157 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_WITHOUT_ACCEPTEDWITHSEC)] = "";
2158 }
2159 index++;
2160 }
2161
2162 Set<TypeDesignationBase<?>> typeDesigantionSet = group.getTypeDesignations();
2163 List<TypeDesignationBase<?>> designationList = new ArrayList<>();
2164 designationList.addAll(typeDesigantionSet);
2165 Collections.sort(designationList, new TypeComparator());
2166
2167 List<TaggedText> list = new ArrayList<>();
2168 if (!designationList.isEmpty()) {
2169 TypeDesignationSetContainer manager = new TypeDesignationSetContainer(group);
2170 list.addAll(new TypeDesignationSetFormatter(true, false, false).toTaggedText(manager));
2171 }
2172 String typeTextDesignations = "";
2173 //The typeDesignationManager does not handle the textual typeDesignations
2174 for (TypeDesignationBase<?> typeDes: designationList) {
2175 if (typeDes instanceof TextualTypeDesignation) {
2176 typeTextDesignations = typeTextDesignations + ((TextualTypeDesignation)typeDes).getText(Language.getDefaultLanguage());
2177 String typeDesStateRefs = "";
2178 if (typeDes.getDesignationSource() != null ){
2179 typeDesStateRefs = "[";
2180 NamedSource source = typeDes.getDesignationSource();
2181 if (source.getCitation() != null){
2182 typeDesStateRefs += "fide " + OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2183 }
2184 typeDesStateRefs += "]";
2185 }else if (typeDes.getSources() != null && !typeDes.getSources().isEmpty()){
2186 typeDesStateRefs = "[";
2187 for (IdentifiableSource source: typeDes.getSources()) {
2188 if (source.getCitation() != null){
2189 typeDesStateRefs += "fide " +OriginalSourceFormatter.INSTANCE.format(source.getCitation(), null);
2190 }
2191 }
2192
2193 typeDesStateRefs += "]";
2194 }
2195
2196 typeTextDesignations = typeTextDesignations + typeDesStateRefs +"; ";
2197
2198 }else if (typeDes instanceof SpecimenTypeDesignation){
2199 DerivedUnit specimen = ((SpecimenTypeDesignation)typeDes).getTypeSpecimen();
2200 if(specimen != null && !state.getSpecimenStore().contains( specimen.getUuid())){
2201 handleSpecimen(state, specimen);
2202 }
2203 }
2204 }
2205 if (typeTextDesignations.equals("; ")) {
2206 typeTextDesignations = "";
2207 }
2208 if (StringUtils.isNotBlank(typeTextDesignations)) {
2209 typeTextDesignations = typeTextDesignations.substring(0, typeTextDesignations.length()-2);
2210 }
2211 String specimenTypeString = !list.isEmpty()? createTypeDesignationString(list, true, typifiedNames.get(0).isSpecies() || typifiedNames.get(0).isInfraSpecific()):"";
2212
2213 if (StringUtils.isNotBlank(specimenTypeString)) {
2214 if (!specimenTypeString.endsWith(".")) {
2215 specimenTypeString = specimenTypeString + ".";
2216 }
2217 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = specimenTypeString;
2218
2219 } else {
2220 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
2221 }
2222 if (StringUtils.isNotBlank(typeTextDesignations)) {
2223 if (!typeTextDesignations.endsWith(".")) {
2224 typeTextDesignations = typeTextDesignations + ".";
2225 }
2226 csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = typeTextDesignations;
2227
2228 } else {
2229 csvLine[table.getIndex(CdmLightExportTable.TYPE_CACHE)] = "";
2230 }
2231 state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
2232 } catch (Exception e) {
2233 state.getResult().addException(e, "An unexpected error occurred when handling homotypic group "
2234 + cdmBaseStr(group) + ": " + e.getMessage());
2235 }
2236 }
2237
2238 private String createTypeDesignationString(List<TaggedText> list, boolean isHomotypicGroup, boolean isSpecimenTypeDesignation) {
2239 StringBuffer homotypicalGroupTypeDesignationString = new StringBuffer();
2240
2241 for (TaggedText text : list) {
2242 if (text == null || text.getText() == null){
2243 continue; //just in case
2244 }
2245 if ((text.getText().equalsIgnoreCase("Type:") //should not happen anymore
2246 || text.getText().equalsIgnoreCase("Nametype:") //should not happen anymore
2247 || (text.getType().equals(TagEnum.name) && !isHomotypicGroup))) {
2248 // do nothing
2249 }else if (text.getType().equals(TagEnum.reference)) {
2250 homotypicalGroupTypeDesignationString.append(text.getText());
2251 }else if (text.getType().equals(TagEnum.name)){
2252 if (!isSpecimenTypeDesignation){
2253 homotypicalGroupTypeDesignationString
2254 .append("<i>"+text.getText()+"</i> ");
2255 }
2256 }else if (text.getType().equals(TagEnum.typeDesignation) ) {
2257 if(isSpecimenTypeDesignation){
2258 homotypicalGroupTypeDesignationString
2259 .append(text.getText().replace(").", "").replace("(", "").replace(")", ""));
2260 }else{
2261 homotypicalGroupTypeDesignationString
2262 .append(text.getText());
2263 }
2264
2265 } else {
2266 homotypicalGroupTypeDesignationString.append(text.getText());
2267 }
2268 }
2269
2270 String typeDesignations = homotypicalGroupTypeDesignationString.toString();
2271 typeDesignations = typeDesignations.trim();
2272
2273 if (typeDesignations.endsWith(";")){
2274 typeDesignations = typeDesignations.substring(0, typeDesignations.length()-1);
2275 }
2276 typeDesignations += ".";
2277 typeDesignations = typeDesignations.replace("..", ".");
2278 typeDesignations = typeDesignations.replace(". .", ".");
2279 typeDesignations = typeDesignations.replace("; \u2261", " \u2261 ");
2280
2281 if (typeDesignations.trim().equals(".")) {
2282 typeDesignations = null;
2283 }
2284
2285 return typeDesignations;
2286 }
2287
2288 private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
2289 try {
2290 String basionymStart = "(";
2291 String basionymEnd = ") ";
2292 String exAuthorSeperator = " ex ";
2293 TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
2294 TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
2295 TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
2296 TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
2297
2298 String combinationAuthorString = "";
2299 if (combinationAuthor != null) {
2300 combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
2301 if (combinationAuthor instanceof Team) {
2302 combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
2303 } else {
2304 Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
2305 combinationAuthorString = createTropicosAuthorString(person);
2306 }
2307 }
2308 String exCombinationAuthorString = "";
2309 if (exCombinationAuthor != null) {
2310 exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
2311 if (exCombinationAuthor instanceof Team) {
2312 exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
2313 } else {
2314 Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
2315 exCombinationAuthorString = createTropicosAuthorString(person);
2316 }
2317 }
2318
2319 String basionymAuthorString = "";
2320 if (basionymAuthor != null) {
2321 basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
2322 if (basionymAuthor instanceof Team) {
2323 basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
2324 } else {
2325 Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
2326 basionymAuthorString = createTropicosAuthorString(person);
2327 }
2328 }
2329
2330 String exBasionymAuthorString = "";
2331
2332 if (exBasionymAuthor != null) {
2333 exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
2334 if (exBasionymAuthor instanceof Team) {
2335 exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
2336
2337 } else {
2338 Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
2339 exBasionymAuthorString = createTropicosAuthorString(person);
2340 }
2341 }
2342 String completeAuthorString = name.getNameCache() + " ";
2343
2344 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2345 || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart : "";
2346 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString))
2347 ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator) : "";
2348 completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString)) ? CdmUtils.Nz(basionymAuthorString) : "";
2349 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)
2350 || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd : "";
2351 completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString))
2352 ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator) : "";
2353 completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString)) ? CdmUtils.Nz(combinationAuthorString)
2354 : "";
2355
2356 return completeAuthorString;
2357 } catch (Exception e) {
2358 state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for "
2359 + cdmBaseStr(name) + ": " + e.getMessage());
2360 return null;
2361 }
2362 }
2363
2364 private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
2365 String combinationAuthorString;
2366 Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
2367 Team tempTeam = Team.NewInstance();
2368 for (Person teamMember : team.getTeamMembers()) {
2369 combinationAuthorString = createTropicosAuthorString(teamMember);
2370 Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
2371 tempTeam.addTeamMember(tempPerson);
2372 }
2373 combinationAuthorString = tempTeam.generateTitle();
2374 return combinationAuthorString;
2375 }
2376
2377 private String createTropicosAuthorString(Person teamMember) {
2378 String nomAuthorString = "";
2379 String[] splittedAuthorString = null;
2380 if (teamMember == null) {
2381 return nomAuthorString;
2382 }
2383
2384 if (teamMember.getGivenName() != null) {
2385 String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
2386 splittedAuthorString = givenNameString.split("\\s");
2387 for (String split : splittedAuthorString) {
2388 if (!StringUtils.isBlank(split)) {
2389 nomAuthorString += split.substring(0, 1);
2390 nomAuthorString += ".";
2391 }
2392 }
2393 }
2394 if (teamMember.getFamilyName() != null) {
2395 String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
2396 splittedAuthorString = familyNameString.split("\\s");
2397 for (String split : splittedAuthorString) {
2398 nomAuthorString += " " + split;
2399 }
2400 }
2401 if (isBlank(nomAuthorString.trim())) {
2402 if (teamMember.getTitleCache() != null) {
2403 String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
2404 splittedAuthorString = titleCacheString.split("\\s");
2405 } else {
2406 splittedAuthorString = new String[0];
2407 }
2408
2409 int index = 0;
2410 for (String split : splittedAuthorString) {
2411 if (index < splittedAuthorString.length - 1 && (split.length() == 1 || split.endsWith("."))) {
2412 nomAuthorString += split;
2413 } else {
2414 nomAuthorString = nomAuthorString + " " + split;
2415 }
2416 index++;
2417 }
2418 }
2419 return nomAuthorString.trim();
2420 }
2421
2422 private void handleReference(CdmLightExportState state, Reference reference) {
2423 try {
2424 state.addReferenceToStore(reference);
2425 CdmLightExportTable table = CdmLightExportTable.REFERENCE;
2426 reference = HibernateProxyHelper.deproxy(reference);
2427
2428 handleIdentifier(state, reference);
2429 String[] csvLine = new String[table.getSize()];
2430 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
2431 // TODO short citations correctly
2432 String shortCitation = OriginalSourceFormatter.INSTANCE_WITH_YEAR_BRACKETS.format(reference, null); // Should be Author(year) like in Taxon.sec
2433 csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
2434 // TODO get preferred title
2435 csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.isProtectedTitleCache()
2436 ? reference.getTitleCache() : reference.getTitle();
2437 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.isProtectedAbbrevTitleCache()
2438 ? reference.getAbbrevTitleCache() : reference.getAbbrevTitle();
2439 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
2440 // TBC
2441 csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
2442 csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
2443 csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
2444 csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
2445 csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
2446 csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
2447 csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
2448 csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
2449 csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
2450 csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
2451 csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
2452 csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
2453
2454 if (reference.getAuthorship() != null) {
2455 csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
2456 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, reference.getAuthorship());
2457 }
2458
2459 csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
2460 if (reference.getInReference() != null
2461 && !state.getReferenceStore().contains(reference.getInReference().getUuid())) {
2462 handleReference(state, reference.getInReference());
2463 }
2464 if (reference.getInstitution() != null) {
2465 csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();
2466 }
2467 if (reference.getLsid() != null) {
2468 csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();
2469 }
2470 if (reference.getSchool() != null) {
2471 csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();
2472 }
2473 if (reference.getUri() != null) {
2474 csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();
2475 }
2476 csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
2477
2478 state.getProcessor().put(table, reference, csvLine);
2479 } catch (Exception e) {
2480 state.getResult().addException(e, "An unexpected error occurred when handling reference "
2481 + cdmBaseStr(reference) + ": " + e.getMessage());
2482 }
2483 }
2484
2485 private String createFullAuthorship(Reference reference) {
2486 TeamOrPersonBase<?> authorship = reference.getAuthorship();
2487 String fullAuthorship = "";
2488 if (authorship == null) {
2489 return null;
2490 }
2491 authorship = HibernateProxyHelper.deproxy(authorship);
2492 if (authorship instanceof Person) {
2493 fullAuthorship = ((Person) authorship).getTitleCache();
2494
2495 } else if (authorship instanceof Team) {
2496
2497 Team authorTeam = (Team)authorship;
2498 fullAuthorship = authorTeam.cacheStrategy().getTitleCache(authorTeam);
2499 }
2500 return fullAuthorship;
2501 }
2502
2503 private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase<?> specimen) {
2504 try {
2505 state.addSpecimenToStore(specimen);
2506 CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
2507 String specimenId = getId(state, specimen);
2508 String[] csvLine = new String[table.getSize()];
2509
2510 /*
2511 * SpecimenCitation = “El Salvador, Municipio La Libertad, San
2512 * Diego, El Amatal, 14.4.1993, González 159” [Auch ohne Punkt] ->
2513 * FieldUnit TitleCache HerbariumAbbrev = “B” [wie gehabt]
2514 * HerbariumCode
2515 *
2516 */
2517
2518 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
2519 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
2520 Collection<FieldUnit> fieldUnits = this.getOccurrenceService().findFieldUnits(specimen.getUuid(), null);
2521 if (fieldUnits.size() == 1) {
2522 Iterator<FieldUnit> iterator = fieldUnits.iterator();
2523 if (iterator.hasNext()){
2524 FieldUnit fieldUnit = iterator.next();
2525 csvLine[table.getIndex(CdmLightExportTable.FIELDUNIT_CITATION)] = fieldUnit.getTitleCache();
2526 }
2527 }
2528 if (specimen.isInstanceOf(DerivedUnit.class)){
2529 DerivedUnit derivedUnit = (DerivedUnit) specimen;
2530 if (!StringUtils.isBlank(derivedUnit.getBarcode())){
2531 csvLine[table.getIndex(CdmLightExportTable.BARCODE)] = derivedUnit.getBarcode();
2532 }
2533 if (!StringUtils.isBlank(derivedUnit.getAccessionNumber())){
2534 csvLine[table.getIndex(CdmLightExportTable.ACCESSION_NUMBER)] = derivedUnit.getAccessionNumber();
2535 }
2536 if (!StringUtils.isBlank(derivedUnit.getCatalogNumber())){
2537 csvLine[table.getIndex(CdmLightExportTable.CATALOGUE_NUMBER)] = derivedUnit.getCatalogNumber();
2538 }
2539 }
2540
2541 csvLine[table.getIndex(CdmLightExportTable.PREFERREDSTABLE_ID)] = specimen.getPreferredStableUri() != null? specimen.getPreferredStableUri().toString(): null;
2542 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractMediaURIs(state,
2543 specimen.getDescriptions(), Feature.IMAGE());
2544 if (specimen instanceof DerivedUnit) {
2545 DerivedUnit derivedUnit = HibernateProxyHelper.deproxy(specimen, DerivedUnit.class);
2546 if (derivedUnit.getCollection() != null) {
2547 csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection()
2548 .getCode();
2549 }
2550
2551 if (specimen instanceof MediaSpecimen) {
2552 MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
2553 Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
2554 String mediaUris = extractMediaUris(it);
2555 csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
2556
2557 }
2558
2559 if (derivedUnit.getDerivedFrom() != null) {
2560 for (SpecimenOrObservationBase<?> original : derivedUnit.getDerivedFrom().getOriginals()) {
2561 // TODO: What to do if there are more then one
2562 // FieldUnit??
2563 if (original instanceof FieldUnit) {
2564 FieldUnit fieldUnit = (FieldUnit) original;
2565 csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
2566
2567 GatheringEvent gathering = fieldUnit.getGatheringEvent();
2568 if (gathering != null) {
2569 if (gathering.getLocality() != null) {
2570 csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality()
2571 .getText();
2572 }
2573 if (gathering.getCountry() != null) {
2574 csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry()
2575 .getLabel();
2576 }
2577 csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(
2578 state, gathering, fieldUnit);
2579
2580 if (gathering.getGatheringDate() != null) {
2581 csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering
2582 .getGatheringDate().toString();
2583 }
2584 if (!gathering.getCollectingAreas().isEmpty()) {
2585 int index = 0;
2586 csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
2587 for (NamedArea area : gathering.getCollectingAreas()) {
2588 if (index == 0) {
2589 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getLevel() != null?area
2590 .getLevel().getLabel():"";
2591 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
2592 }
2593 if (index == 1) {
2594 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getLevel() != null?area
2595 .getLevel().getLabel():"";
2596 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
2597 }
2598 if (index == 2) {
2599 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getLevel() != null?area
2600 .getLevel().getLabel():"";
2601 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
2602 }
2603 if (index == 3) {
2604 csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
2605 break;
2606 }
2607 index++;
2608 }
2609 }
2610 }
2611 }
2612 }
2613 } else {
2614 state.getResult().addWarning("The specimen with uuid " + specimen.getUuid()
2615 + " is not an DerivedUnit.");
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
2727 }