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