adapt sec ref title with datePublished freeText
[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.Collections;
14 import java.util.HashSet;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import org.apache.commons.lang3.StringUtils;
21 import org.springframework.stereotype.Component;
22
23 import eu.etaxonomy.cdm.common.CdmUtils;
24 import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
25 import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
26 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
27 import eu.etaxonomy.cdm.io.common.CdmExportBase;
28 import eu.etaxonomy.cdm.io.common.ExportResult.ExportResultState;
29 import eu.etaxonomy.cdm.io.common.ICdmExport;
30 import eu.etaxonomy.cdm.io.common.TaxonNodeOutStreamPartitioner;
31 import eu.etaxonomy.cdm.io.common.XmlExportState;
32 import eu.etaxonomy.cdm.io.common.mapping.out.IExportTransformer;
33 import eu.etaxonomy.cdm.model.agent.AgentBase;
34 import eu.etaxonomy.cdm.model.agent.Person;
35 import eu.etaxonomy.cdm.model.agent.Team;
36 import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
37 import eu.etaxonomy.cdm.model.common.Annotation;
38 import eu.etaxonomy.cdm.model.common.AnnotationType;
39 import eu.etaxonomy.cdm.model.common.CdmBase;
40 import eu.etaxonomy.cdm.model.common.DefinedTerm;
41 import eu.etaxonomy.cdm.model.common.ICdmBase;
42 import eu.etaxonomy.cdm.model.common.IIdentifiableEntity;
43 import eu.etaxonomy.cdm.model.common.Language;
44 import eu.etaxonomy.cdm.model.common.LanguageString;
45 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
46 import eu.etaxonomy.cdm.model.description.DescriptionBase;
47 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
48 import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
49 import eu.etaxonomy.cdm.model.description.Distribution;
50 import eu.etaxonomy.cdm.model.description.Feature;
51 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
52 import eu.etaxonomy.cdm.model.description.SpecimenDescription;
53 import eu.etaxonomy.cdm.model.description.TaxonDescription;
54 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
55 import eu.etaxonomy.cdm.model.description.TextData;
56 import eu.etaxonomy.cdm.model.location.NamedArea;
57 import eu.etaxonomy.cdm.model.media.Media;
58 import eu.etaxonomy.cdm.model.media.MediaRepresentation;
59 import eu.etaxonomy.cdm.model.media.MediaRepresentationPart;
60 import eu.etaxonomy.cdm.model.name.HomotypicalGroup;
61 import eu.etaxonomy.cdm.model.name.HomotypicalGroupNameComparator;
62 import eu.etaxonomy.cdm.model.name.NameTypeDesignation;
63 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
64 import eu.etaxonomy.cdm.model.name.Rank;
65 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
66 import eu.etaxonomy.cdm.model.name.TaxonName;
67 import eu.etaxonomy.cdm.model.name.TypeComparator;
68 import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
69 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
70 import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
71 import eu.etaxonomy.cdm.model.occurrence.GatheringEvent;
72 import eu.etaxonomy.cdm.model.occurrence.MediaSpecimen;
73 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
74 import eu.etaxonomy.cdm.model.reference.Reference;
75 import eu.etaxonomy.cdm.model.reference.ReferenceType;
76 import eu.etaxonomy.cdm.model.taxon.Synonym;
77 import eu.etaxonomy.cdm.model.taxon.Taxon;
78 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
79 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
80 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
81 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
82
83 /**
84 * @author k.luther
85 * @since 15.03.2017
86 */
87 @Component
88 public class CdmLightClassificationExport
89 extends CdmExportBase<CdmLightExportConfigurator, CdmLightExportState, IExportTransformer, File>
90 implements ICdmExport<CdmLightExportConfigurator, CdmLightExportState>{
91
92
93 private static final long serialVersionUID = 2518643632756927053L;
94 private static final String STD_TEAM_CONCATINATION = ", ";
95 private static final String FINAL_TEAM_CONCATINATION = " & ";
96
97
98 private static final String IPNI_NAME_IDENTIFIER = "Ipni Name Identifier";
99 private static final String TROPICOS_NAME_IDENTIFIER = "Tropicos Name Identifier";
100 private static final String WFO_NAME_IDENTIFIER = "WFO Name Identifier";
101
102 public CdmLightClassificationExport() {
103 super();
104 this.ioName = this.getClass().getSimpleName();
105
106 }
107
108 @Override
109 public long countSteps(CdmLightExportState state) {
110 TaxonNodeFilter filter = state.getConfig().getTaxonNodeFilter();
111 return taxonNodeService.count(filter);
112 }
113
114
115 /**
116 * {@inheritDoc}
117 */
118 @Override
119 protected void doInvoke(CdmLightExportState state) {
120 try {
121
122 IProgressMonitor monitor = state.getConfig().getProgressMonitor();
123 CdmLightExportConfigurator config = state.getConfig();
124 config.setFieldsTerminatedBy(",");
125
126 // if (config.getTaxonNodeFilter().getTaxonNodesFilter().isEmpty() && config.getTaxonNodeFilter().getClassificationFilter().isEmpty()){
127 // //TODO
128 // state.setEmptyData();
129 // return;
130 // }
131
132
133
134 // for (LogicFilter<Classification> classificationFilter : config.getTaxonNodeFilter().getClassificationFilter()){
135 // UUID classificationUuid = classificationFilter.getUuid();
136 // Classification classification = getClassificationService().find(classificationUuid);
137 // if (classification == null){
138 // String message = String.format("Classification for given classification UUID not found. No data imported for %s", classificationUuid.toString());
139 // state.getResult().addWarning(message);
140 // }else{
141 // TaxonNode root = classification.getRootNode();
142 // UUID uuid = root.getUuid();
143 // root = getTaxonNodeService().load(uuid);
144 // handleSingleClassification(state, root.getUuid());
145 // }
146 // }
147
148
149 @SuppressWarnings("unchecked")
150 TaxonNodeOutStreamPartitioner<XmlExportState> partitioner
151 = TaxonNodeOutStreamPartitioner.NewInstance(
152 this, state, state.getConfig().getTaxonNodeFilter(),
153 100, monitor, null);
154
155
156 monitor.subTask("Start partitioning");
157
158 TaxonNode node = partitioner.next();
159 while (node != null){
160 handleTaxonNode(state, node);
161 node = partitioner.next();
162 }
163
164
165 // for (LogicFilter<TaxonNode> taxonNodeFilter : config.getTaxonNodeFilter().getTaxonNodesFilter()){
166 // UUID nodeUuid = taxonNodeFilter.getUuid();
167 // handleSingleClassification(state, nodeUuid);
168 // }
169 state.getProcessor().createFinalResult(state);
170 } catch (Exception e) {
171 state.getResult().addException(e, "An unexpected error occurred in main method doInvoke() " +
172 e.getMessage());
173 }
174 }
175
176 /**
177 * @param state
178 * @param classificationUuid
179 */
180 private void handleTaxonNode(CdmLightExportState state, TaxonNode taxonNode) {
181
182 if (taxonNode == null){
183 String message = "TaxonNode for given taxon node UUID not found. ";
184 //TODO
185 state.getResult().addWarning(message);
186 }else{
187 try {
188 TaxonNode root = taxonNode;
189 if (root.hasTaxon()){
190 handleTaxon(state, root);
191 }else{
192 // for (TaxonNode child : root.getChildNodes()){
193 // handleTaxon(state, child);
194 // //TODO progress monitor
195 // }
196 }
197 } catch (Exception e) {
198 state.getResult().addException(e, "An unexpected error occurred when handling classification " +
199 taxonNode.getUuid() + ": " + e.getMessage() + e.getStackTrace());
200 }
201 }
202 }
203
204 /**
205 * @param state
206 * @param taxon
207 */
208 private void handleTaxon(CdmLightExportState state, TaxonNode taxonNode) {
209 try{
210 // Taxon taxon = taxonNode.getTaxon();
211 if (taxonNode == null){
212 state.getResult().addError ("The taxonNode was null.", "handleTaxon");
213 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
214 return;
215 }
216 if (taxonNode.getTaxon() == null){
217 state.getResult().addError ("There was a taxon node without a taxon: " + taxonNode.getUuid(), "handleTaxon");
218 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
219 }else{
220 Taxon taxon = HibernateProxyHelper.deproxy(taxonNode.getTaxon(), Taxon.class);
221
222 try{
223 TaxonName name = taxon.getName();
224 handleName(state, name);
225 for (Synonym syn : taxon.getSynonyms()){
226 handleSynonym(state, syn);
227 }
228 for (TaxonRelationship rel : taxon.getProParteAndPartialSynonymRelations()){
229 handleProPartePartialMisapplied(state, rel);
230 }
231 for (TaxonRelationship rel : taxon.getMisappliedNameRelations()){
232 handleProPartePartialMisapplied(state, rel);
233 }
234
235 CdmLightExportTable table = CdmLightExportTable.TAXON;
236 String[] csvLine = new String[table.getSize()];
237
238 csvLine[table.getIndex(CdmLightExportTable.TAXON_ID)] = getId(state, taxon);
239 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
240 Taxon parent = (taxonNode.getParent()==null) ? null : taxonNode.getParent().getTaxon();
241 csvLine[table.getIndex(CdmLightExportTable.PARENT_FK)] = getId(state, parent);
242 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, taxon.getSec());
243 if (taxon.getSec().getDatePublished().getFreeText() != null){
244 String sec_string = taxon.getSec().getTitleCache() + ". " + taxon.getSec().getDatePublished().getFreeText();
245 sec_string = sec_string.replace("..", ".");
246 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = sec_string;
247 }else{
248 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(taxon.getSec());
249 }
250 if (state.getReferenceFromStore(taxon.getSec().getId()) == null){
251 handleReference(state, taxon.getSec());
252 }
253 csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_ID)] = getId(state, taxonNode.getClassification());
254 csvLine[table.getIndex(CdmLightExportTable.CLASSIFICATION_TITLE)] = taxonNode.getClassification().getTitleCache();
255
256 state.getProcessor().put(table, taxon, csvLine);
257 handleDescriptions(state, taxon);
258 }catch(Exception e){
259 state.getResult().addException (e, "An unexpected problem occurred when trying to export "
260 + "taxon with id " + taxon.getId());
261 state.getResult().setState(ExportResultState.INCOMPLETE_WITH_ERROR);
262 }
263 }
264
265 taxonNode.removeNullValueFromChildren();
266 // for (TaxonNode child: taxonNode.getChildNodes()){
267 // handleTaxon(state, child);
268 // }
269 }catch (Exception e){
270 state.getResult().addException(e, "An unexpected error occurred when handling the taxon node of " +
271 cdmBaseStr(taxonNode.getTaxon()) + ": " + e.getMessage());
272 }
273 }
274
275
276 /**
277 * @param state
278 * @param taxon
279 */
280 private void handleDescriptions(CdmLightExportState state, CdmBase cdmBase) {
281 try{
282 if (cdmBase instanceof Taxon){
283 Taxon taxon = HibernateProxyHelper.deproxy(cdmBase, Taxon.class);
284 Set<TaxonDescription> descriptions = taxon.getDescriptions();
285 List<DescriptionElementBase> simpleFacts = new ArrayList<>();
286 List<DescriptionElementBase> specimenFacts = new ArrayList<>();
287 List<DescriptionElementBase> distributionFacts = new ArrayList<>();
288 List<DescriptionElementBase> commonNameFacts = new ArrayList<>();
289 List<DescriptionElementBase> usageFacts = new ArrayList<>();
290 for (TaxonDescription description: descriptions){
291 if (description.getElements() != null){
292 for (DescriptionElementBase element: description.getElements()){
293 element = CdmBase.deproxy(element);
294 if (element.getFeature().equals(Feature.COMMON_NAME())){
295 commonNameFacts.add(element);
296 }else if (element.getFeature().equals(Feature.DISTRIBUTION())){
297 distributionFacts.add(element);
298 }else if (element instanceof IndividualsAssociation || isSpecimenFeature(element.getFeature())){
299 specimenFacts.add(element);
300 }else{
301 simpleFacts.add(element);
302 }
303 }
304 }
305 }
306 if (!commonNameFacts.isEmpty()){
307 handleCommonNameFacts(state, taxon, commonNameFacts);
308 }
309 if (!distributionFacts.isEmpty()){
310 handleDistributionFacts(state, taxon, distributionFacts);
311 }
312 if (!specimenFacts.isEmpty()){
313 handleSpecimenFacts(state, taxon, specimenFacts);
314 }
315 if (!simpleFacts.isEmpty()){
316 handleSimpleFacts(state, taxon, simpleFacts);
317 }
318 } else if (cdmBase instanceof TaxonName){
319 TaxonName name = CdmBase.deproxy(cdmBase, TaxonName.class);
320 Set<TaxonNameDescription> descriptions = name.getDescriptions();
321 List<DescriptionElementBase> simpleFacts = new ArrayList<>();
322 for (TaxonNameDescription description: descriptions){
323 if (description.getElements() != null){
324 for (DescriptionElementBase element: description.getElements()){
325 if (!element.getFeature().equals(Feature.PROTOLOGUE())){
326 simpleFacts.add(element);
327 }
328 }
329 }
330 }
331 if (!simpleFacts.isEmpty()){
332 handleSimpleFacts(state, name, simpleFacts);
333 }
334 }
335 }catch (Exception e){
336 state.getResult().addException(e, "An unexpected error occurred when handling description of" +
337 cdmBaseStr(cdmBase) + ": " + e.getMessage());
338 }
339 }
340
341
342 /**
343 * @param feature
344 * @return
345 */
346 private boolean isSpecimenFeature(Feature feature) {
347 //TODO allow user defined specimen features
348 if (feature == null){
349 return false;
350 }else if (feature.isSupportsIndividualAssociation()){
351 return true;
352 }else{
353 return feature.equals(Feature.SPECIMEN()) || feature.equals(Feature.INDIVIDUALS_ASSOCIATION())
354 || feature.equals(Feature.MATERIALS_EXAMINED()) || feature.equals(Feature.OBSERVATION())
355 || feature.equals(Feature.OCCURRENCE())
356 ;
357 }
358 }
359
360 /**
361 * @param state
362 * @param taxon
363 * @param simpleFacts
364 */
365 private void handleSimpleFacts(CdmLightExportState state, CdmBase cdmBase,
366 List<DescriptionElementBase> simpleFacts) {
367 try {
368 CdmLightExportTable table = CdmLightExportTable.SIMPLE_FACT;
369 CdmLightExportTable tableMedia = CdmLightExportTable.MEDIA;
370 for (DescriptionElementBase element: simpleFacts){
371 if (element.getModifyingText().isEmpty() && !element.getMedia().isEmpty()){
372 handleSimpleMediaFact(state, cdmBase, tableMedia, element);
373 }else{
374 handleSingleSimpleFact(state, cdmBase, table, element);
375 }
376 }
377 } catch (Exception e) {
378 state.getResult().addException(e, "An unexpected error occurred when handling simple facts for " +
379 cdmBaseStr(cdmBase) + ": " + e.getMessage());
380 }
381 }
382
383 /**
384 * @param state
385 * @param cdmBase
386 * @param tableMedia
387 * @param element
388 */
389 private void handleSimpleMediaFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
390 DescriptionElementBase element) {
391 try {
392 String[] csvLine;
393 handleSource(state, element, CdmLightExportTable.MEDIA);
394
395 if (element instanceof TextData){
396 TextData textData = (TextData)element;
397 csvLine = new String[table.getSize()];
398 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
399 if (cdmBase instanceof Taxon){
400 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
401 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
402 }else if (cdmBase instanceof TaxonName){
403 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
404 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
405 }
406
407
408 String mediaUris = "";
409 for (Media media: textData.getMedia()){
410 String mediaString = extractMediaUris(media.getRepresentations().iterator());
411 if (!StringUtils.isBlank(mediaString)){
412 mediaUris += mediaString + ";";
413 }
414 else{
415 state.getResult().addWarning("Empty Media object for "
416 + cdmBase.getUserFriendlyTypeName() + " " + cdmBase.getUuid()
417 + " (media: " + media.getUuid() + ")");
418 }
419 }
420 csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
421
422 }
423 } catch (Exception e) {
424 state.getResult().addException(e, "An unexpected error occurred when handling single simple fact " +
425 cdmBaseStr(element) + ": " + e.getMessage());
426 }
427
428 }
429
430 /**
431 * @param state
432 * @param cdmBase
433 * @param table
434 * @param element
435 */
436 private void handleSingleSimpleFact(CdmLightExportState state, CdmBase cdmBase, CdmLightExportTable table,
437 DescriptionElementBase element) {
438 try {
439 String[] csvLine;
440 handleSource(state, element, CdmLightExportTable.SIMPLE_FACT);
441
442 if (element instanceof TextData){
443 TextData textData = (TextData)element;
444 csvLine = new String[table.getSize()];
445 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
446 if (cdmBase instanceof Taxon){
447 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
448 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = "";
449 }else if (cdmBase instanceof TaxonName){
450 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = "";
451 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, cdmBase);
452 }
453 csvLine[table.getIndex(CdmLightExportTable.FACT_CATEGORY)] = textData.getFeature().getLabel();
454
455 String mediaUris = "";
456 for (Media media: textData.getMedia()){
457 String mediaString = extractMediaUris(media.getRepresentations().iterator());
458 if (!StringUtils.isBlank(mediaString)){
459 mediaUris += mediaString + ";";
460 }
461 else{
462 state.getResult().addWarning("Empty Media object for uuid: " +
463 cdmBase.getUuid() + " uuid of media: " + media.getUuid());
464 }
465 }
466 csvLine[table.getIndex(CdmLightExportTable.MEDIA_URI)] = mediaUris;
467 if (textData.getFeature().equals(Feature.CITATION())){
468 // csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, cdmBase);
469 state.getProcessor().put(table, textData, csvLine);
470 }else if (!textData.getMultilanguageText().isEmpty()){
471 for (Language language: textData.getMultilanguageText().keySet()){
472 String[] csvLineLanguage = csvLine.clone();
473 LanguageString langString = textData.getLanguageText(language);
474 String text = langString.getText();
475 if (state.getConfig().isFilterIntextReferences()){
476 text = filterIntextReferences(langString.getText());
477 }
478 csvLineLanguage[table.getIndex(CdmLightExportTable.FACT_TEXT)] = text;
479 csvLineLanguage[table.getIndex(CdmLightExportTable.LANGUAGE)] = language.getLabel();
480 state.getProcessor().put(table, textData, csvLineLanguage);
481 }
482 } else{
483 state.getProcessor().put(table, textData, csvLine);
484 }
485 }
486 } catch (Exception e) {
487 state.getResult().addException(e, "An unexpected error occurred when handling single simple fact " +
488 cdmBaseStr(element) + ": " + e.getMessage());
489 }
490 }
491
492
493 /**
494 * @param text
495 * @return
496 */
497 private String filterIntextReferences(String text) {
498 /*
499 * (<cdm:reference cdmId='fbd19251-efee-4ded-b780-915000f66d41' intextId='1352d42c-e201-4155-a02a-55360d3b563e'>Ridley in Fl. Malay Pen. 3 (1924) 22</cdm:reference>)
500 */
501
502 String newText = text.replaceAll("<cdm:reference cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>","");
503 newText = newText.replaceAll("</cdm:reference>","");
504
505 newText = newText.replaceAll("<cdm:key cdmId='[a-z0-9\\-]*' intextId='[a-z0-9\\-]*'>","");
506 newText = newText.replaceAll("</cdm:key>","");
507 return newText;
508 }
509
510 /**
511 * @param state
512 * @param specimenFacts
513 */
514 private void handleSpecimenFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> specimenFacts) {
515 CdmLightExportTable table = CdmLightExportTable.SPECIMEN_FACT;
516
517 for (DescriptionElementBase element: specimenFacts){
518 try {
519 String[] csvLine = new String[table.getSize()];
520 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
521 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
522 handleSource(state, element, table);
523 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_NOTES)] = createAnnotationsString(element.getAnnotations());
524
525 if (element instanceof IndividualsAssociation){
526
527 IndividualsAssociation indAssociation = (IndividualsAssociation)element;
528 if (indAssociation.getAssociatedSpecimenOrObservation() == null){
529 state.getResult().addWarning("There is an individual association with no specimen associated (Taxon "+ taxon.getTitleCache() + "(" + taxon.getUuid() +"). Could not be exported.");
530 continue;
531 }else{
532 if (state.getSpecimenFromStore(indAssociation.getAssociatedSpecimenOrObservation().getId()) == null){
533 SpecimenOrObservationBase<?> specimenBase = HibernateProxyHelper.deproxy(indAssociation.getAssociatedSpecimenOrObservation());
534
535 if (specimenBase instanceof SpecimenOrObservationBase){
536 SpecimenOrObservationBase derivedUnit = specimenBase;
537 handleSpecimen(state, derivedUnit);
538 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, indAssociation.getAssociatedSpecimenOrObservation());
539 }else{
540 //field units are not supported
541 state.getResult().addError("The associated Specimen of taxon " + taxon.getUuid() + " is not an DerivedUnit. Could not be exported.");
542
543 }
544 }
545 }
546 } else if (element instanceof TextData){
547 TextData textData = HibernateProxyHelper.deproxy(element, TextData.class);
548 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_DESCRIPTION)] = createMultilanguageString(textData.getMultilanguageText());
549 }
550 state.getProcessor().put(table, element, csvLine);
551 } catch (Exception e) {
552 state.getResult().addException(e, "An unexpected error occurred when handling single specimen fact " +
553 cdmBaseStr(element) + ": " + e.getMessage());
554 }
555 }
556 }
557
558 /**
559 * @param multilanguageText
560 * @return
561 */
562 private String createMultilanguageString(Map<Language, LanguageString> multilanguageText) {
563 String text = "";
564 int index = multilanguageText.size();
565 for(LanguageString langString: multilanguageText.values()){
566 text += langString.getText();
567 if (index > 1){
568 text += "; ";
569 }
570 index --;
571 }
572
573 return text;
574 }
575
576 /**
577 * @param annotations
578 * @return
579 */
580 private String createAnnotationsString(Set<Annotation> annotations) {
581 StringBuffer strBuff = new StringBuffer();
582
583 for (Annotation ann:annotations){
584 if (ann.getAnnotationType() == null ||!ann.getAnnotationType().equals(AnnotationType.TECHNICAL())){
585 strBuff.append(ann.getText());
586 strBuff.append("; ");
587 }
588 }
589
590 if (strBuff.length() > 2){
591 return strBuff.substring(0, strBuff.length()-2);
592 }else{
593 return null;
594 }
595 }
596
597 /**
598 * @param state
599 * @param taxon
600 * @param element
601 */
602 private void handleSource(CdmLightExportState state, DescriptionElementBase element, CdmLightExportTable factsTable) {
603 CdmLightExportTable table = CdmLightExportTable.FACT_SOURCES;
604 try {
605 Set<DescriptionElementSource> sources = element.getSources();
606
607 for (DescriptionElementSource source: sources){
608
609 String[] csvLine = new String[table.getSize()];
610 Reference ref = source.getCitation();
611 if ((ref == null) && (source.getNameUsedInSource() == null)){
612 continue;
613 }
614 if (ref != null){
615 if (state.getReferenceFromStore(ref.getId()) == null){
616 handleReference(state, ref);
617
618 }
619 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, ref);
620 }
621 csvLine[table.getIndex(CdmLightExportTable.FACT_FK)] = getId(state, element);
622
623 csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)] = getId(state, source.getNameUsedInSource());
624 csvLine[table.getIndex(CdmLightExportTable.FACT_TYPE)] = factsTable.getTableName();
625 if ( StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)]) && StringUtils.isBlank(csvLine[table.getIndex(CdmLightExportTable.NAME_IN_SOURCE_FK)])){
626 continue;
627 }
628 state.getProcessor().put(table, source, csvLine);
629
630 }
631 } catch (Exception e) {
632 state.getResult().addException(e, "An unexpected error occurred when handling single source " +
633 cdmBaseStr(element) + ": " + e.getMessage());
634 }
635
636 }
637
638 /**
639 * @param state
640 * @param distributionFacts
641 */
642 private void handleDistributionFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> distributionFacts) {
643 CdmLightExportTable table = CdmLightExportTable.GEOGRAPHIC_AREA_FACT;
644
645 for (DescriptionElementBase element: distributionFacts){
646 try {
647 if (element instanceof Distribution){
648 String[] csvLine = new String[table.getSize()];
649 Distribution distribution = (Distribution)element;
650 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
651 handleSource(state, element, table);
652 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
653 if (distribution.getArea() != null){
654 csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = distribution.getArea().getLabel();
655 }
656 if (distribution.getStatus() != null){
657 csvLine[table.getIndex(CdmLightExportTable.STATUS_LABEL)] = distribution.getStatus().getLabel();
658 }
659 state.getProcessor().put(table, distribution, csvLine);
660 } else{
661 state.getResult().addError("The distribution description for the taxon " + taxon.getUuid() + " is not of type distribution. Could not be exported. UUID of the description element: " + element.getUuid());
662 }
663 } catch (Exception e) {
664 state.getResult().addException(e, "An unexpected error occurred when handling single distribution " +
665 cdmBaseStr(element) + ": " + e.getMessage());
666 }
667 }
668 }
669
670 /**
671 * @param state
672 * @param commonNameFacts
673 */
674 private void handleCommonNameFacts(CdmLightExportState state, Taxon taxon, List<DescriptionElementBase> commonNameFacts) {
675 CdmLightExportTable table = CdmLightExportTable.COMMON_NAME_FACT;
676
677 for (DescriptionElementBase element: commonNameFacts){
678 try {
679 if (element instanceof CommonTaxonName){
680 String[] csvLine = new String[table.getSize()];
681 CommonTaxonName commonName = (CommonTaxonName)element;
682 csvLine[table.getIndex(CdmLightExportTable.FACT_ID)] = getId(state, element);
683 handleSource(state, element, table);
684 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, taxon);
685 if (commonName.getName() != null){csvLine[table.getIndex(CdmLightExportTable.FACT_TEXT)] = commonName.getName();}
686 if (commonName.getLanguage() != null){csvLine[table.getIndex(CdmLightExportTable.LANGUAGE)] = commonName.getLanguage().getLabel();}
687 if (commonName.getArea() != null){ csvLine[table.getIndex(CdmLightExportTable.AREA_LABEL)] = commonName.getArea().getLabel();}
688 state.getProcessor().put(table, commonName, csvLine);
689 } else{
690 state.getResult().addError("The distribution description for the taxon " + taxon.getUuid() + " is not of type distribution. Could not be exported. UUID of the description element: " + element.getUuid());
691 }
692 } catch (Exception e) {
693 state.getResult().addException(e, "An unexpected error occurred when handling single common name " +
694 cdmBaseStr(element) + ": " + e.getMessage());
695 }
696 }
697 }
698
699 /**
700 * @param sec
701 * @return
702 */
703 private String getTitleCache(IIdentifiableEntity identEntity) {
704 if (identEntity == null){
705 return "";
706 }
707 //TODO refresh?
708 return identEntity.getTitleCache();
709 }
710
711 /**
712 * @param state
713 * @param taxon
714 * @return
715 */
716 private String getId(CdmLightExportState state, ICdmBase cdmBase) {
717 if (cdmBase == null){
718 return "";
719 }
720 //TODO make configurable
721 return cdmBase.getUuid().toString();
722 }
723
724 /**
725 * @param state
726 * @param synonym
727 */
728 private void handleSynonym(CdmLightExportState state, Synonym synonym) {
729 try {
730 if (isUnpublished(state.getConfig(), synonym)){
731 return;
732 }
733 TaxonName name = synonym.getName();
734 handleName(state, name);
735
736 CdmLightExportTable table = CdmLightExportTable.SYNONYM;
737 String[] csvLine = new String[table.getSize()];
738
739 csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, synonym);
740 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, synonym.getAcceptedTaxon());
741 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
742 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synonym.getSec());
743 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synonym.getSec());
744
745 state.getProcessor().put(table, synonym, csvLine);
746 } catch (Exception e) {
747 state.getResult().addException(e, "An unexpected error occurred when handling synonym " +
748 cdmBaseStr(synonym) + ": " + e.getMessage());
749 }
750 }
751
752
753 /**
754 * Handles Misapplied names (including pro parte and partial as well as
755 * pro parte and partial synonyms
756 * @param state
757 * @param rel
758 */
759 private void handleProPartePartialMisapplied(CdmLightExportState state, TaxonRelationship rel) {
760 try {
761 Taxon ppSyonym = rel.getFromTaxon();
762 if (isUnpublished(state.getConfig(), ppSyonym)){
763 return;
764 }
765 TaxonName name = ppSyonym.getName();
766 handleName(state, name);
767
768 CdmLightExportTable table = CdmLightExportTable.SYNONYM;
769 String[] csvLine = new String[table.getSize()];
770
771 csvLine[table.getIndex(CdmLightExportTable.SYNONYM_ID)] = getId(state, rel);
772 csvLine[table.getIndex(CdmLightExportTable.TAXON_FK)] = getId(state, rel.getToTaxon());
773 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId(state, name);
774
775 Reference secRef = ppSyonym.getSec();
776 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE_FK)] = getId(state, secRef);
777 csvLine[table.getIndex(CdmLightExportTable.SEC_REFERENCE)] = getTitleCache(secRef);
778 Reference synSecRef = rel.getCitation();
779 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE_FK)] = getId(state, synSecRef);
780 csvLine[table.getIndex(CdmLightExportTable.SYN_SEC_REFERENCE)] = getTitleCache(synSecRef);
781
782 //pro parte type
783 TaxonRelationshipType type = rel.getType();
784 csvLine[table.getIndex(CdmLightExportTable.IS_PRO_PARTE)] = type.isProParte()? "1":"0";
785 csvLine[table.getIndex(CdmLightExportTable.IS_PARTIAL)] = type.isPartial()? "1":"0";
786 csvLine[table.getIndex(CdmLightExportTable.IS_MISAPPLIED)] = type.isAnyMisappliedName()? "1":"0";
787
788 state.getProcessor().put(table, ppSyonym, csvLine);
789 } catch (Exception e) {
790 state.getResult().addException(e, "An unexpected error occurred when handling "
791 + "pro parte/partial synonym relationship " +
792 cdmBaseStr(rel) + ": " + e.getMessage());
793 }
794
795 }
796
797
798 /**
799 * @param state
800 * @param name
801 */
802 private void handleName(CdmLightExportState state, TaxonName name) {
803 if (name == null){
804 return;
805 }
806 try {
807 Rank rank = name.getRank();
808 CdmLightExportTable table = CdmLightExportTable.SCIENTIFIC_NAME;
809 name = HibernateProxyHelper.deproxy(name);
810 String[] csvLine = new String[table.getSize()];
811
812 csvLine[table.getIndex(CdmLightExportTable.NAME_ID)] = getId(state, name);
813 if (name.getLsid() != null){
814 csvLine[table.getIndex(CdmLightExportTable.LSID)] = name.getLsid().getLsid();
815 }else{
816 csvLine[table.getIndex(CdmLightExportTable.LSID)] = "";
817 }
818
819 handleIdentifier(state, name);
820 handleDescriptions(state, name);
821
822 csvLine[table.getIndex(CdmLightExportTable.RANK)] = getTitleCache(rank);
823 if (rank != null){
824 csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = String.valueOf(rank.getOrderIndex());
825 if (rank.isInfraGeneric()){
826 try {
827 csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_RANK)] = name.getRank().getInfraGenericMarker();
828 } catch (UnknownCdmTypeException e) {
829 state.getResult().addError("Infrageneric marker expected but not available for rank " + name.getRank().getTitleCache());
830 }
831 }
832 if (rank.isInfraSpecific()){
833 csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_RANK)] = name.getRank().getAbbreviation();
834 }
835 }else{
836 csvLine[table.getIndex(CdmLightExportTable.RANK_SEQUENCE)] = "";
837 }
838 if (name.isProtectedTitleCache()){
839 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] =name.getTitleCache();
840 }else{
841 //TODO: adapt the tropicos titlecache creation
842 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_WITH_AUTHORS)] = name.getTitleCache();
843 }
844 csvLine[table.getIndex(CdmLightExportTable.FULL_NAME_NO_AUTHORS)] = name.getNameCache();
845 csvLine[table.getIndex(CdmLightExportTable.GENUS_UNINOMIAL)] = name.getGenusOrUninomial();
846
847 csvLine[table.getIndex(CdmLightExportTable.INFRAGENERIC_EPITHET)] = name.getInfraGenericEpithet();
848 csvLine[table.getIndex(CdmLightExportTable.SPECIFIC_EPITHET)] = name.getSpecificEpithet();
849
850 csvLine[table.getIndex(CdmLightExportTable.INFRASPECIFIC_EPITHET)] = name.getInfraSpecificEpithet();
851 csvLine[table.getIndex(CdmLightExportTable.BAS_AUTHORTEAM_FK)] = getId(state,name.getBasionymAuthorship());
852 if (name.getBasionymAuthorship() != null){
853 if (state.getAuthorFromStore(name.getBasionymAuthorship().getId()) == null) {
854 handleAuthor(state, name.getBasionymAuthorship());
855 }
856 }
857 csvLine[table.getIndex(CdmLightExportTable.BAS_EX_AUTHORTEAM_FK)] = getId(state, name.getExBasionymAuthorship());
858 if (name.getExBasionymAuthorship() != null){
859 if (state.getAuthorFromStore(name.getExBasionymAuthorship().getId()) == null) {
860 handleAuthor(state, name.getExBasionymAuthorship());
861 }
862
863 }
864 csvLine[table.getIndex(CdmLightExportTable.COMB_AUTHORTEAM_FK)] = getId(state,name.getCombinationAuthorship());
865 if (name.getCombinationAuthorship() != null){
866 if (state.getAuthorFromStore(name.getCombinationAuthorship().getId()) == null) {
867 handleAuthor(state, name.getCombinationAuthorship());
868 }
869 }
870 csvLine[table.getIndex(CdmLightExportTable.COMB_EX_AUTHORTEAM_FK)] = getId(state, name.getExCombinationAuthorship());
871 if (name.getExCombinationAuthorship() != null){
872 if (state.getAuthorFromStore(name.getExCombinationAuthorship().getId()) == null) {
873 handleAuthor(state, name.getExCombinationAuthorship());
874 }
875
876 }
877
878 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TEAM_STRING)] = name.getAuthorshipCache();
879
880 Reference nomRef = name.getNomenclaturalReference();
881
882 if (nomRef != null){
883 if (state.getReferenceFromStore(nomRef.getId()) == null){
884 handleReference(state, nomRef);
885 }
886 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_FK)] = getId(state, nomRef);
887 csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = nomRef.getType().name();
888 if (nomRef.getVolume() != null){
889 csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = nomRef.getVolume();
890 csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
891 }
892 if (nomRef.getDatePublished() != null){
893 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = nomRef.getTimePeriodPublishedString();
894 csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = nomRef.getDatePublished().getYear();
895 csvLine[table.getIndex(CdmLightExportTable.VERBATIM_DATE)] = nomRef.getDatePublished().getVerbatimDate();
896 }
897 if (name.getNomenclaturalMicroReference() != null){
898 csvLine[table.getIndex(CdmLightExportTable.DETAIL)] = name.getNomenclaturalMicroReference();
899 }
900 nomRef = HibernateProxyHelper.deproxy(nomRef);
901 if (nomRef.getInReference() != null){
902 Reference inReference = nomRef.getInReference();
903 if (inReference.getDatePublished() != null && nomRef.getDatePublished() == null){
904 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = inReference.getDatePublishedString();
905 csvLine[table.getIndex(CdmLightExportTable.YEAR_PUBLISHED)] = inReference.getDatePublished().getYear();
906 }
907 if (nomRef.getVolume() == null && inReference.getVolume() != null){
908 csvLine[table.getIndex(CdmLightExportTable.VOLUME_ISSUE)] = inReference.getVolume();
909 csvLine[table.getIndex(CdmLightExportTable.COLLATION)] = createCollatation(name);
910 }
911 if (inReference.getInReference() != null){
912 inReference = inReference.getInReference();
913 }
914 if (inReference.getAbbrevTitle() == null){
915 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(inReference.getAbbrevTitleCache());
916 }else{
917 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(inReference.getAbbrevTitle());
918 }
919 if (inReference.getTitle() == null){
920 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitleCache());
921 }else{
922 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(inReference.getTitle());
923 }
924
925
926 TeamOrPersonBase<?> author = inReference.getAuthorship();
927 if (author != null && (nomRef.isOfType(ReferenceType.BookSection) || nomRef.isOfType(ReferenceType.Section))){
928 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = CdmUtils.Nz(author.getNomenclaturalTitle());
929 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils.Nz(author.getTitleCache());
930 }else{
931 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
932 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
933 }
934 }else{
935 if (nomRef.getAbbrevTitle() == null){
936 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(nomRef.getAbbrevTitleCache());
937 }else{
938 csvLine[table.getIndex(CdmLightExportTable.ABBREV_TITLE)] = CdmUtils.Nz(nomRef.getAbbrevTitle());
939 }
940 if (nomRef.getTitle() == null){
941 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitleCache());
942 }else{
943 csvLine[table.getIndex(CdmLightExportTable.FULL_TITLE)] = CdmUtils.Nz(nomRef.getTitle());
944 }
945 TeamOrPersonBase<?> author = nomRef.getAuthorship();
946 if (author != null ){
947 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = CdmUtils.Nz(author.getNomenclaturalTitle());
948 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = CdmUtils.Nz(author.getTitleCache());
949 }else{
950 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_AUTHOR)] = "";
951 csvLine[table.getIndex(CdmLightExportTable.FULL_REF_AUTHOR)] = "";
952 }
953
954 }
955 }else{
956 csvLine[table.getIndex(CdmLightExportTable.PUBLICATION_TYPE)] = "";
957 }
958
959
960
961 /*
962 * Collation
963
964 Detail
965
966
967 TitlePageYear
968 */
969 Set<TaxonNameDescription> descriptions = name.getDescriptions();
970 String protologueUriString = extractURIs(state, descriptions, Feature.PROTOLOGUE());
971
972 csvLine[table.getIndex(CdmLightExportTable.PROTOLOGUE_URI)] = protologueUriString;
973
974 if (name.getStatus() == null || name.getStatus().isEmpty()){
975 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = "";
976 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = "";
977 }else{
978
979 String statusStringAbbrev = extractStatusString(state, name, true);
980 String statusString = extractStatusString(state, name, false);
981
982 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS)] = statusString.trim();
983 csvLine[table.getIndex(CdmLightExportTable.NOM_STATUS_ABBREV)] = statusStringAbbrev.trim();
984 }
985
986 HomotypicalGroup group =name.getHomotypicalGroup();
987
988 if (state.getHomotypicalGroupFromStore(group.getId()) == null){
989 handleHomotypicalGroup(state, group);
990 }
991 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_FK)] = getId(state, group);
992 List<TaxonName> typifiedNames = new ArrayList<>();
993 typifiedNames.addAll(group.getTypifiedNames());
994 Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
995 Integer seqNumber= typifiedNames.indexOf(name);
996 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_SEQ)] = String.valueOf(seqNumber);
997 state.getProcessor().put(table, name, csvLine);
998
999 /*
1000 *
1001 Tropicos_ID
1002 IPNI_ID
1003
1004
1005 InfragenericRank
1006
1007
1008 InfraspecificRank
1009 Collation
1010 Volume (Issue)
1011 Detail
1012 DatePublished
1013 YearPublished
1014 TitlePageYear
1015
1016
1017
1018 HomotypicGroupSequenceNumber
1019
1020
1021 *
1022 */
1023 } catch (Exception e) {
1024 state.getResult().addException(e, "An unexpected error occurred when handling synonym " +
1025 cdmBaseStr(name) + ": " + e.getMessage());
1026 }
1027 }
1028
1029 /**
1030 * @return
1031 */
1032 private String createCollatation(TaxonName name) {
1033 String collation = "";
1034 if (name.getNomenclaturalReference() != null){
1035 Reference ref = name.getNomenclaturalReference();
1036 collation = getVolume(ref);
1037 }
1038 if (name.getNomenclaturalMicroReference() != null){
1039 if (!StringUtils.isBlank(collation)){
1040 collation += ":";
1041 }
1042 collation +=name.getNomenclaturalMicroReference();
1043 }
1044
1045 return collation;
1046 }
1047
1048 /**
1049 * @param nomenclaturalReference
1050 * @return
1051 */
1052 private String getVolume(Reference reference) {
1053 if (reference.getVolume() != null){
1054 return reference.getVolume();
1055 }else if (reference.getInReference() != null){
1056 if (reference.getInReference().getVolume() != null){
1057 return reference.getInReference().getVolume();
1058 }
1059 }
1060 return null;
1061 }
1062
1063 /**
1064 * @param state
1065 * @param name
1066 */
1067 private void handleIdentifier(CdmLightExportState state, TaxonName name) {
1068 CdmLightExportTable table = CdmLightExportTable.IDENTIFIER;
1069 String[] csvLine;
1070 try {
1071 Set<String> IPNIidentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_IPNI());
1072 Set<String> tropicosIdentifiers = name.getIdentifiers(DefinedTerm.IDENTIFIER_NAME_TROPICOS());
1073 Set<String> WFOIdentifiers = name.getIdentifiers(DefinedTerm.uuidWfoNameIdentifier);
1074 if (!IPNIidentifiers.isEmpty()){
1075 csvLine = new String[table.getSize()];
1076 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
1077 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = IPNI_NAME_IDENTIFIER;
1078 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(IPNIidentifiers);
1079 state.getProcessor().put(table, name, csvLine);
1080 }
1081 if (!tropicosIdentifiers.isEmpty()){
1082 csvLine = new String[table.getSize()];
1083 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
1084 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = TROPICOS_NAME_IDENTIFIER;
1085 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(tropicosIdentifiers);
1086 state.getProcessor().put(table, name, csvLine);
1087 }
1088 if (!WFOIdentifiers.isEmpty()){
1089 csvLine = new String[table.getSize()];
1090 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = getId( state, name);
1091 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_TYPE)] = WFO_NAME_IDENTIFIER;
1092 csvLine[table.getIndex(CdmLightExportTable.IDENTIFIER_IDS)] = extractIdentifier(WFOIdentifiers);
1093 state.getProcessor().put(table, name, csvLine);
1094 }
1095 } catch (Exception e) {
1096 state.getResult().addException(e, "An unexpected error occurred when handling identifiers for " +
1097 cdmBaseStr(name) + ": " + e.getMessage());
1098
1099 }
1100 }
1101
1102 /**
1103 * @param tropicosIdentifiers
1104 */
1105 private String extractIdentifier(Set<String> identifierSet) {
1106
1107 String identifierString = "";
1108 for (String identifier: identifierSet){
1109 if (!StringUtils.isBlank(identifierString)){
1110 identifierString += ", ";
1111 }
1112 identifierString += identifier;
1113 }
1114
1115 return identifierString;
1116 }
1117
1118 /**
1119 * @param state
1120 * @param descriptions
1121 * @return
1122 */
1123 private String extractURIs(CdmLightExportState state,
1124 Set<? extends DescriptionBase<?>> descriptionsSet, Feature feature) {
1125 String mediaUriString = "";
1126 SpecimenDescription specimenDescription;
1127 TaxonDescription taxonDescription;
1128 TaxonNameDescription nameDescription;
1129 Set<DescriptionElementBase> elements = new HashSet<>();
1130 for (DescriptionBase<?> description : descriptionsSet){
1131 try {
1132 if (!description.getElements().isEmpty()){
1133 if (description instanceof SpecimenDescription){
1134 specimenDescription = (SpecimenDescription)description;
1135 elements = specimenDescription.getElements();
1136 }else if (description instanceof TaxonDescription){
1137 taxonDescription = (TaxonDescription) description;
1138 elements = taxonDescription.getElements();
1139 } else if (description instanceof TaxonNameDescription){
1140 nameDescription = (TaxonNameDescription) description;
1141 elements = nameDescription.getElements();
1142 }
1143
1144 for (DescriptionElementBase element : elements){
1145 Feature entityFeature = HibernateProxyHelper.deproxy(element.getFeature());
1146 if (entityFeature.equals(feature)){
1147 if (!element.getMedia().isEmpty()){
1148 List<Media> media = element.getMedia();
1149 for (Media mediaElement: media){
1150 Iterator<MediaRepresentation> it = mediaElement.getRepresentations().iterator();
1151 mediaUriString = extractMediaUris(it);
1152 }
1153 }
1154 }
1155 }
1156 }
1157 } catch (Exception e) {
1158 state.getResult().addException(e, "An unexpected error occurred when extracting media URIs for " +
1159 cdmBaseStr(description) + ": " + e.getMessage());
1160 }
1161 }
1162 return mediaUriString;
1163 }
1164
1165 /**
1166 * @param state
1167 * @param basionymAuthorship
1168 */
1169 private void handleAuthor(CdmLightExportState state, TeamOrPersonBase<?> author) {
1170 try {
1171 if (state.getAuthorFromStore(author.getId()) != null){
1172 return;
1173 }
1174 state.addAuthorToStore(author);
1175 CdmLightExportTable table = CdmLightExportTable.NOMENCLATURAL_AUTHOR;
1176 String[] csvLine = new String[table.getSize()];
1177 CdmLightExportTable tableAuthorRel = CdmLightExportTable.NOMENCLATURAL_AUTHOR_TEAM_RELATION;
1178 String[] csvLineRel = new String[tableAuthorRel.getSize()];
1179 String[] csvLineMember = new String[table.getSize()];
1180 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, author);
1181 csvLine[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = author.getNomenclaturalTitle();
1182 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = author.getTitleCache();
1183 author = HibernateProxyHelper.deproxy(author);
1184 if (author instanceof Person){
1185 Person authorPerson = (Person)author;
1186 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = authorPerson.getGivenName();
1187 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = authorPerson.getFamilyName();
1188 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = authorPerson.getPrefix();
1189 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = authorPerson.getSuffix();
1190 } else{
1191 // create an entry in rel table and all members in author table, check whether the team members already in author table
1192
1193 Team authorTeam = (Team)author;
1194 int index = 0;
1195 for (Person member: authorTeam.getTeamMembers()){
1196 csvLineRel = new String[tableAuthorRel.getSize()];
1197 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_FK)] = getId(state, authorTeam);
1198 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state, member);
1199 csvLineRel[tableAuthorRel.getIndex(CdmLightExportTable.AUTHOR_TEAM_SEQ_NUMBER)] = String.valueOf(index);
1200 state.getProcessor().put(tableAuthorRel, authorTeam.getId() +":" +member.getId(), csvLineRel);
1201
1202 if (state.getAuthorFromStore(member.getId()) == null){
1203 state.addAuthorToStore(member);
1204 csvLineMember = new String[table.getSize()];
1205 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_ID)] = getId(state, member);
1206 csvLineMember[table.getIndex(CdmLightExportTable.ABBREV_AUTHOR)] = member.getNomenclaturalTitle();
1207 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_TITLE)] = member.getTitleCache();
1208 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_GIVEN_NAME)] = member.getGivenName();
1209 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_FAMILY_NAME)] = member.getFamilyName();
1210 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_PREFIX)] = member.getPrefix();
1211 csvLineMember[table.getIndex(CdmLightExportTable.AUTHOR_SUFFIX)] = member.getSuffix();
1212 state.getProcessor().put(table, member, csvLineMember);
1213 }
1214 index++;
1215
1216 }
1217 }
1218 state.getProcessor().put(table, author, csvLine);
1219 } catch (Exception e) {
1220 state.getResult().addException(e, "An unexpected error occurred when handling author " +
1221 cdmBaseStr(author) + ": " + e.getMessage());
1222 }
1223 }
1224
1225 /**
1226 * @param state
1227 * @param name
1228 * @param statusString
1229 * @return
1230 */
1231 private String extractStatusString(CdmLightExportState state, TaxonName name, boolean abbrev) {
1232 try {
1233 Set<NomenclaturalStatus> status = name.getStatus();
1234 if (status.isEmpty()){
1235 return "";
1236 }
1237 String statusString = "";
1238 for (NomenclaturalStatus nameStatus: status){
1239 if (nameStatus != null){
1240 if (abbrev){
1241 if (nameStatus.getType() != null){
1242 statusString += nameStatus.getType().getIdInVocabulary();
1243 }
1244 }else{
1245 if (nameStatus.getType() != null){
1246 statusString += nameStatus.getType().getTitleCache();
1247 }
1248 }
1249 if (!abbrev){
1250
1251 if (nameStatus.getRuleConsidered() != null && !StringUtils.isBlank(nameStatus.getRuleConsidered())){
1252 statusString += " " + nameStatus.getRuleConsidered();
1253 }
1254 if (nameStatus.getCitation() != null){
1255 statusString += " " + nameStatus.getCitation().getTitleCache();
1256 }
1257 if (nameStatus.getCitationMicroReference() != null && !StringUtils.isBlank(nameStatus.getCitationMicroReference())){
1258 statusString += " " + nameStatus.getCitationMicroReference();
1259 }
1260 }
1261 statusString += " ";
1262 }
1263 }
1264 return statusString;
1265 } catch (Exception e) {
1266 state.getResult().addException(e, "An unexpected error occurred when extracting status string for " +
1267 cdmBaseStr(name) + ": " + e.getMessage());
1268 return "";
1269 }
1270 }
1271
1272 /**
1273 * @param group
1274 */
1275 private void handleHomotypicalGroup(CdmLightExportState state, HomotypicalGroup group) {
1276 try {
1277 state.addHomotypicalGroupToStore(group);
1278 CdmLightExportTable table = CdmLightExportTable.HOMOTYPIC_GROUP;
1279 String[] csvLine = new String[table.getSize()];
1280
1281 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_ID)] = getId(state, group);
1282 List<TaxonName> typifiedNames = new ArrayList<>();
1283 typifiedNames.addAll(group.getTypifiedNames());
1284 Collections.sort(typifiedNames, new HomotypicalGroupNameComparator(null, true));
1285 String typifiedNamesString = "";
1286 for (TaxonName name: typifiedNames){
1287 //Concatenated output string for homotypic group (names and citations) + status + some name relations (e.g. “non”)
1288 //TODO: nameRelations, which and how to display
1289
1290
1291 typifiedNamesString += name.getTitleCache()+ extractStatusString(state, name, true) + "; ";
1292 }
1293 typifiedNamesString = typifiedNamesString.substring(0, typifiedNamesString.length()-2);
1294 if (typifiedNamesString != null){
1295 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = typifiedNamesString.trim();
1296 }else{
1297 csvLine[table.getIndex(CdmLightExportTable.HOMOTYPIC_GROUP_STRING)] = "";
1298 }
1299 Set<TypeDesignationBase> typeDesigantions = group.getTypeDesignations();
1300 List<TypeDesignationBase> designationList = new ArrayList<>();
1301 designationList.addAll(typeDesigantions);
1302 Collections.sort(designationList, new TypeComparator());
1303 StringBuffer typeDesignationString = new StringBuffer();
1304 for (TypeDesignationBase typeDesignation: typeDesigantions){
1305 if (typeDesignation != null && typeDesignation.getTypeStatus() != null){
1306 typeDesignationString.append(typeDesignation.getTypeStatus().getTitleCache() + ": ");
1307 }
1308 if (typeDesignation instanceof SpecimenTypeDesignation){
1309 if (((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen() != null){
1310 typeDesignationString.append(((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen().getTitleCache());
1311 handleSpecimen(state, ((SpecimenTypeDesignation)typeDesignation).getTypeSpecimen());
1312 }
1313 }else{
1314 if (((NameTypeDesignation)typeDesignation).getTypeName() != null){
1315 typeDesignationString.append(((NameTypeDesignation)typeDesignation).getTypeName().getTitleCache());
1316 }
1317 }
1318 if(typeDesignation.getCitation() != null ){
1319 typeDesignationString.append(", "+typeDesignation.getCitation().getTitleCache());
1320 }
1321 //TODO...
1322 /*
1323 * Sortierung:
1324 1. Status der Typen: a) holo, lecto, neo, syn, b) epi, paralecto, c) para (wenn überhaupt) – die jeweiligen iso immer direct mit dazu
1325 2. Land
1326 3. Sammler
1327 4. Nummer
1328
1329 Aufbau der Typusinformationen:
1330 Land: Lokalität mit Höhe und Koordinaten; Datum; Sammler Nummer (Herbar/Barcode, Typusart; Herbar/Barcode, Typusart …)
1331
1332 */
1333 }
1334 String typeDesignations = typeDesignationString.toString();
1335 if (typeDesignations != null){
1336 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = typeDesignations;
1337 }else{
1338 csvLine[table.getIndex(CdmLightExportTable.TYPE_STRING)] = "";
1339 }
1340 state.getProcessor().put(table, String.valueOf(group.getId()), csvLine);
1341 } catch (Exception e) {
1342 state.getResult().addException(e, "An unexpected error occurred when handling homotypic group " +
1343 cdmBaseStr(group) + ": " + e.getMessage());
1344 }
1345 }
1346
1347 /**
1348 * @param name
1349 * @return
1350 */
1351 private String getTropicosTitleCache(CdmLightExportState state, TaxonName name) {
1352 try {
1353 String basionymStart = "(";
1354 String basionymEnd = ") ";
1355 String exAuthorSeperator = " ex ";
1356 TeamOrPersonBase<?> combinationAuthor = name.getCombinationAuthorship();
1357 TeamOrPersonBase<?> exCombinationAuthor = name.getExCombinationAuthorship();
1358 TeamOrPersonBase<?> basionymAuthor = name.getBasionymAuthorship();
1359 TeamOrPersonBase<?> exBasionymAuthor = name.getExBasionymAuthorship();
1360
1361 String combinationAuthorString = "";
1362 if (combinationAuthor != null){
1363 combinationAuthor = HibernateProxyHelper.deproxy(combinationAuthor);
1364 if (combinationAuthor instanceof Team){
1365 combinationAuthorString = createTropicosTeamTitle(combinationAuthor);
1366 }else{
1367 Person person = HibernateProxyHelper.deproxy(combinationAuthor, Person.class);
1368 combinationAuthorString = createTropicosAuthorString(person);
1369 }
1370 }
1371 String exCombinationAuthorString = "";
1372 if (exCombinationAuthor != null){
1373 exCombinationAuthor = HibernateProxyHelper.deproxy(exCombinationAuthor);
1374 if (exCombinationAuthor instanceof Team){
1375 exCombinationAuthorString = createTropicosTeamTitle(exCombinationAuthor);
1376 }else{
1377 Person person = HibernateProxyHelper.deproxy(exCombinationAuthor, Person.class);
1378 exCombinationAuthorString = createTropicosAuthorString(person);
1379 }
1380 }
1381
1382 String basionymAuthorString = "";
1383 if (basionymAuthor != null){
1384 basionymAuthor = HibernateProxyHelper.deproxy(basionymAuthor);
1385 if (basionymAuthor instanceof Team){
1386 basionymAuthorString = createTropicosTeamTitle(basionymAuthor);
1387 }else{
1388 Person person = HibernateProxyHelper.deproxy(basionymAuthor, Person.class);
1389 basionymAuthorString = createTropicosAuthorString(person);
1390 }
1391 }
1392
1393 String exBasionymAuthorString = "";
1394
1395 if (exBasionymAuthor != null){
1396 exBasionymAuthor = HibernateProxyHelper.deproxy(exBasionymAuthor);
1397 if (exBasionymAuthor instanceof Team){
1398 exBasionymAuthorString = createTropicosTeamTitle(exBasionymAuthor);
1399
1400 }else{
1401 Person person = HibernateProxyHelper.deproxy(exBasionymAuthor, Person.class);
1402 exBasionymAuthorString = createTropicosAuthorString(person);
1403 }
1404 }
1405 String completeAuthorString = name.getNameCache() + " ";
1406
1407 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString) || !CdmUtils.isBlank(basionymAuthorString)) ? basionymStart: "";
1408 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString)) ? (CdmUtils.Nz(exBasionymAuthorString) + exAuthorSeperator): "" ;
1409 completeAuthorString += (!CdmUtils.isBlank(basionymAuthorString))? CdmUtils.Nz(basionymAuthorString):"";
1410 completeAuthorString += (!CdmUtils.isBlank(exBasionymAuthorString) || !CdmUtils.isBlank(basionymAuthorString)) ? basionymEnd:"";
1411 completeAuthorString += (!CdmUtils.isBlank(exCombinationAuthorString)) ? (CdmUtils.Nz(exCombinationAuthorString) + exAuthorSeperator): "" ;
1412 completeAuthorString += (!CdmUtils.isBlank(combinationAuthorString))? CdmUtils.Nz(combinationAuthorString):"";
1413
1414
1415 return completeAuthorString;
1416 } catch (Exception e) {
1417 state.getResult().addException(e, "An unexpected error occurred when handling tropicos title cache for " +
1418 cdmBaseStr(name) + ": " + e.getMessage());
1419 return null;
1420 }
1421 }
1422
1423 /**
1424 * @param combinationAuthor
1425 * @return
1426 */
1427 private String createTropicosTeamTitle(TeamOrPersonBase<?> combinationAuthor) {
1428 String combinationAuthorString;
1429 Team team = HibernateProxyHelper.deproxy(combinationAuthor, Team.class);
1430 Team tempTeam = Team.NewInstance();
1431 for (Person teamMember:team.getTeamMembers()){
1432 combinationAuthorString = createTropicosAuthorString(teamMember);
1433 Person tempPerson = Person.NewTitledInstance(combinationAuthorString);
1434 tempTeam.addTeamMember(tempPerson);
1435 }
1436 combinationAuthorString = tempTeam.generateTitle();
1437 return combinationAuthorString;
1438 }
1439
1440 /**
1441 * @param teamMember
1442 */
1443 private String createTropicosAuthorString(Person teamMember) {
1444 String nomAuthorString = "";
1445 String[] splittedAuthorString = null;
1446 if (teamMember == null){
1447 return nomAuthorString;
1448 }
1449
1450 if (teamMember.getGivenName() != null){
1451 String givenNameString = teamMember.getGivenName().replaceAll("\\.", "\\. ");
1452 splittedAuthorString = givenNameString.split("\\s");
1453 for (String split: splittedAuthorString){
1454 if (!StringUtils.isBlank(split)){
1455 nomAuthorString += split.substring(0, 1);
1456 nomAuthorString += ".";
1457 }
1458 }
1459 }
1460 if (teamMember.getFamilyName() != null){
1461 String familyNameString = teamMember.getFamilyName().replaceAll("\\.", "\\. ");
1462 splittedAuthorString = familyNameString.split("\\s");
1463 for (String split: splittedAuthorString){
1464 nomAuthorString += " " +split;
1465 }
1466 }
1467 if (StringUtils.isBlank(nomAuthorString.trim())){
1468 if (teamMember.getTitleCache() != null) {
1469 String titleCacheString = teamMember.getTitleCache().replaceAll("\\.", "\\. ");
1470 splittedAuthorString = titleCacheString.split("\\s");
1471 }
1472
1473
1474 int index = 0;
1475 for (String split: splittedAuthorString){
1476 if ( index < splittedAuthorString.length-1 && (split.length()==1 || split.endsWith("."))){
1477 nomAuthorString += split;
1478 }else{
1479 nomAuthorString = nomAuthorString +" "+ split;
1480 }
1481 index++;
1482 }
1483 }
1484 return nomAuthorString.trim();
1485 }
1486
1487 /**
1488 * @param state
1489 * @param name
1490 */
1491 private void handleReference(CdmLightExportState state, Reference reference) {
1492 try {
1493 state.addReferenceToStore(reference);
1494 CdmLightExportTable table = CdmLightExportTable.REFERENCE;
1495
1496 String[] csvLine = new String[table.getSize()];
1497 csvLine[table.getIndex(CdmLightExportTable.REFERENCE_ID)] = getId(state, reference);
1498 //TODO short citations correctly
1499 String shortCitation = createShortCitation(reference); //Should be Author(year) like in Taxon.sec
1500 csvLine[table.getIndex(CdmLightExportTable.BIBLIO_SHORT_CITATION)] = shortCitation;
1501 //TODO get preferred title
1502 csvLine[table.getIndex(CdmLightExportTable.REF_TITLE)] = reference.getTitle();
1503 csvLine[table.getIndex(CdmLightExportTable.ABBREV_REF_TITLE)] = reference.getAbbrevTitle();
1504 csvLine[table.getIndex(CdmLightExportTable.DATE_PUBLISHED)] = reference.getDatePublishedString();
1505 //TBC
1506 csvLine[table.getIndex(CdmLightExportTable.EDITION)] = reference.getEdition();
1507 csvLine[table.getIndex(CdmLightExportTable.EDITOR)] = reference.getEditor();
1508 csvLine[table.getIndex(CdmLightExportTable.ISBN)] = reference.getIsbn();
1509 csvLine[table.getIndex(CdmLightExportTable.ISSN)] = reference.getIssn();
1510 csvLine[table.getIndex(CdmLightExportTable.ORGANISATION)] = reference.getOrganization();
1511 csvLine[table.getIndex(CdmLightExportTable.PAGES)] = reference.getPages();
1512 csvLine[table.getIndex(CdmLightExportTable.PLACE_PUBLISHED)] = reference.getPlacePublished();
1513 csvLine[table.getIndex(CdmLightExportTable.PUBLISHER)] = reference.getPublisher();
1514 csvLine[table.getIndex(CdmLightExportTable.REF_ABSTRACT)] = reference.getReferenceAbstract();
1515 csvLine[table.getIndex(CdmLightExportTable.SERIES_PART)] = reference.getSeriesPart();
1516 csvLine[table.getIndex(CdmLightExportTable.VOLUME)] = reference.getVolume();
1517 csvLine[table.getIndex(CdmLightExportTable.YEAR)] = reference.getYear();
1518
1519 if ( reference.getAuthorship() != null){
1520 csvLine[table.getIndex(CdmLightExportTable.AUTHORSHIP_TITLE)] = createFullAuthorship(reference);
1521 csvLine[table.getIndex(CdmLightExportTable.AUTHOR_FK)] = getId(state,reference.getAuthorship());
1522 }
1523
1524 csvLine[table.getIndex(CdmLightExportTable.IN_REFERENCE)] = getId(state, reference.getInReference());
1525 if (reference.getInReference() != null && state.getReferenceFromStore(reference.getInReference().getId()) == null){
1526 handleReference(state, reference.getInReference());
1527 }
1528 if ( reference.getInstitution() != null){ csvLine[table.getIndex(CdmLightExportTable.INSTITUTION)] = reference.getInstitution().getTitleCache();}
1529 if ( reference.getLsid() != null){ csvLine[table.getIndex(CdmLightExportTable.LSID)] = reference.getLsid().getLsid();}
1530 if ( reference.getSchool() != null){ csvLine[table.getIndex(CdmLightExportTable.SCHOOL)] = reference.getSchool().getTitleCache();}
1531 if ( reference.getUri() != null){ csvLine[table.getIndex(CdmLightExportTable.URI)] = reference.getUri().toString();}
1532 csvLine[table.getIndex(CdmLightExportTable.REF_TYPE)] = reference.getType().getKey();
1533
1534 state.getProcessor().put(table, reference, csvLine);
1535 } catch (Exception e) {
1536 state.getResult().addException(e, "An unexpected error occurred when handling reference " +
1537 cdmBaseStr(reference) + ": " + e.getMessage());
1538 }
1539
1540 }
1541
1542
1543 /**
1544 * @param reference
1545 * @return
1546 */
1547 private String createShortCitation(Reference reference) {
1548 TeamOrPersonBase<?> authorship = reference.getAuthorship();
1549 String shortCitation = "";
1550 if (authorship == null) {
1551 return null;
1552 }
1553 authorship = HibernateProxyHelper.deproxy(authorship);
1554 if (authorship instanceof Person){
1555 shortCitation = ((Person)authorship).getFamilyName();
1556 if (StringUtils.isBlank(shortCitation) ){
1557 shortCitation = ((Person)authorship).getTitleCache();
1558 }
1559 }
1560 else if (authorship instanceof Team){
1561
1562 Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
1563 int index = 0;
1564
1565 for (Person teamMember : authorTeam.getTeamMembers()){
1566 index++;
1567 if (index == 3){
1568 shortCitation += " & al.";
1569 break;
1570 }
1571 String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
1572 if (teamMember.getFamilyName() != null){
1573 shortCitation += concat + teamMember.getFamilyName();
1574 }else{
1575 shortCitation += concat + teamMember.getTitleCache();
1576 }
1577
1578 }
1579 if (StringUtils.isBlank(shortCitation)){
1580 shortCitation = authorTeam.getTitleCache();
1581 }
1582
1583 }
1584 if (!StringUtils.isBlank(reference.getDatePublished().getFreeText())){
1585 shortCitation = shortCitation + " (" + reference.getDatePublished().getFreeText() + ")";
1586 }else if (!StringUtils.isBlank(reference.getYear()) ){
1587 shortCitation = shortCitation + " (" + reference.getYear() + ")";
1588 }
1589 return shortCitation;
1590 }
1591
1592 /**
1593 * @param reference
1594 * @return
1595 */
1596 private String createFullAuthorship(Reference reference) {
1597 TeamOrPersonBase<?> authorship = reference.getAuthorship();
1598 String fullAuthorship = "";
1599 if (authorship == null) {
1600 return null;
1601 }
1602 authorship = HibernateProxyHelper.deproxy(authorship);
1603 if (authorship instanceof Person){
1604 fullAuthorship = ((Person)authorship).getTitleCache();
1605
1606 }
1607 else if (authorship instanceof Team){
1608
1609 Team authorTeam = HibernateProxyHelper.deproxy(authorship, Team.class);
1610 int index = 0;
1611
1612 for (Person teamMember : authorTeam.getTeamMembers()){
1613 index++;
1614 String concat = concatString(authorTeam, authorTeam.getTeamMembers(), index);
1615 fullAuthorship += concat + teamMember.getTitleCache();
1616 }
1617
1618 }
1619
1620 return fullAuthorship;
1621 }
1622
1623 private static String concatString(Team team, List<Person> teamMembers, int i) {
1624 String concat;
1625 if (i <= 1){
1626 concat = "";
1627 }else if (i < teamMembers.size() || ( team.isHasMoreMembers() && i == teamMembers.size())){
1628 concat = STD_TEAM_CONCATINATION;
1629 }else{
1630 concat = FINAL_TEAM_CONCATINATION;
1631 }
1632 return concat;
1633 }
1634
1635 /*
1636 * TypeDesignation table
1637 * Specimen_Fk
1638 * EditName_Fk
1639 * TypeVerbatimCitation
1640 * TypeCategory
1641 * TypeDesignatedByString
1642 * TypeDesignatedByRef_Fk
1643 */
1644
1645 private void handleSpecimenTypeDesignations(CdmLightExportState state, TaxonName name){
1646 try {
1647 Set<SpecimenTypeDesignation> typeDesignations = name.getSpecimenTypeDesignations();
1648 CdmLightExportTable table = CdmLightExportTable.TYPE_DESIGNATION;
1649 String nameId = getId(state, name);
1650 String[] csvLine = new String[table.getSize()];
1651 for (SpecimenTypeDesignation specimenType: typeDesignations){
1652 csvLine = new String[table.getSize()];
1653 DerivedUnit specimen = specimenType.getTypeSpecimen();
1654 if (state.getSpecimenFromStore(specimen.getId()) == null){
1655 handleSpecimen(state, specimen);
1656 }
1657 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_FK)] = getId(state, specimenType.getTypeSpecimen());
1658 csvLine[table.getIndex(CdmLightExportTable.NAME_FK)] = nameId;
1659 csvLine[table.getIndex(CdmLightExportTable.TYPE_VERBATIM_CITATION)] = specimenType.getTypeSpecimen().generateTitle();
1660 //TODO: add link to existing Vorcabulary
1661 csvLine[table.getIndex(CdmLightExportTable.TYPE_CATEGORY)] = "";
1662 csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_STRING)] = specimenType.getCitation().getTitleCache();
1663 csvLine[table.getIndex(CdmLightExportTable.TYPE_DESIGNATED_BY_REF_FK)] = getId(state, specimenType.getCitation());
1664 }
1665 } catch (Exception e) {
1666 state.getResult().addException(e, "An unexpected error occurred when handling specimen type designations for " +
1667 cdmBaseStr(name) + ": " + e.getMessage());
1668 }
1669 }
1670
1671 /**
1672 * @param state
1673 * @param specimen
1674 */
1675 private void handleSpecimen(CdmLightExportState state, SpecimenOrObservationBase specimen) {
1676 try {
1677 state.addSpecimenToStore(specimen);
1678 CdmLightExportTable table = CdmLightExportTable.SPECIMEN;
1679 String specimenId = getId(state, specimen);
1680 String[] csvLine = new String[table.getSize()];
1681
1682 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_ID)] = specimenId;
1683 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_CITATION)] = specimen.getTitleCache();
1684 csvLine[table.getIndex(CdmLightExportTable.SPECIMEN_IMAGE_URIS)] = extractURIs(state, specimen.getDescriptions(), Feature.IMAGE());
1685 if (specimen instanceof DerivedUnit){
1686 DerivedUnit derivedUnit = (DerivedUnit)specimen;
1687 if (derivedUnit.getCollection() != null){ csvLine[table.getIndex(CdmLightExportTable.HERBARIUM_ABBREV)] = derivedUnit.getCollection().getCode();}
1688
1689 if (specimen instanceof MediaSpecimen){
1690 MediaSpecimen mediaSpecimen = (MediaSpecimen) specimen;
1691 Iterator<MediaRepresentation> it = mediaSpecimen.getMediaSpecimen().getRepresentations().iterator();
1692 String mediaUris = extractMediaUris(it);
1693 csvLine[table.getIndex(CdmLightExportTable.MEDIA_SPECIMEN_URL)] = mediaUris;
1694
1695 }
1696
1697 if (derivedUnit.getDerivedFrom() != null){
1698 for (SpecimenOrObservationBase<?> original: derivedUnit.getDerivedFrom().getOriginals()){
1699 //TODO: What to do if there are more then one FieldUnit??
1700 if (original instanceof FieldUnit){
1701 FieldUnit fieldUnit = (FieldUnit)original;
1702 csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_NUMBER)] = fieldUnit.getFieldNumber();
1703
1704 GatheringEvent gathering = fieldUnit.getGatheringEvent();
1705 if (gathering != null){
1706 if (gathering.getLocality() != null){ csvLine[table.getIndex(CdmLightExportTable.LOCALITY)] = gathering.getLocality().getText();}
1707 if (gathering.getCountry() != null){csvLine[table.getIndex(CdmLightExportTable.COUNTRY)] = gathering.getCountry().getLabel();}
1708 csvLine[table.getIndex(CdmLightExportTable.COLLECTOR_STRING)] = createCollectorString(state, gathering, fieldUnit);
1709 addCollectingAreas(state, gathering);
1710 if (gathering.getGatheringDate() != null){csvLine[table.getIndex(CdmLightExportTable.COLLECTION_DATE)] = gathering.getGatheringDate().toString();}
1711 if (!gathering.getCollectingAreas().isEmpty()){
1712 int index = 0;
1713 csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "0";
1714 for (NamedArea area: gathering.getCollectingAreas()){
1715 if (index == 0){
1716 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY1)] = area.getTermType().getKey();
1717 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME1)] = area.getLabel();
1718 }
1719 if (index == 1){
1720 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY2)] = area.getTermType().getKey();
1721 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME2)] = area.getLabel();
1722 }
1723 if (index == 2){
1724 csvLine[table.getIndex(CdmLightExportTable.AREA_CATEGORY3)] = area.getTermType().getKey();
1725 csvLine[table.getIndex(CdmLightExportTable.AREA_NAME3)] = area.getLabel();
1726 }
1727 if (index == 3){
1728 csvLine[table.getIndex(CdmLightExportTable.FURTHER_AREAS)] = "1";
1729 break;
1730 }
1731 index++;
1732 }
1733 }
1734 }
1735 }
1736 }
1737 }
1738 }
1739
1740 state.getProcessor().put(table, specimen, csvLine);
1741 } catch (Exception e) {
1742 state.getResult().addException(e, "An unexpected error occurred when handling specimen " +
1743 cdmBaseStr(specimen) + ": " + e.getMessage());
1744 }
1745 }
1746
1747 /**
1748 * @param it
1749 */
1750 private String extractMediaUris(Iterator<MediaRepresentation> it) {
1751
1752 String mediaUriString = "";
1753 boolean first = true;
1754 while(it.hasNext()){
1755 MediaRepresentation rep = it.next();
1756 List<MediaRepresentationPart> parts = rep.getParts();
1757 for (MediaRepresentationPart part: parts){
1758 if (first){
1759 if (part.getUri() != null){
1760 mediaUriString += part.getUri().toString();
1761 first = false;
1762 }
1763 }else{
1764 if (part.getUri() != null){
1765 mediaUriString += ", " +part.getUri().toString();
1766 }
1767 }
1768 }
1769 }
1770
1771 return mediaUriString;
1772 }
1773
1774 /**
1775 * @param state
1776 * @param gathering
1777 */
1778 private void addCollectingAreas(CdmLightExportState state, GatheringEvent gathering) {
1779 // TODO implement !!!
1780
1781 if (!gathering.getCollectingAreas().isEmpty()){
1782 state.getResult().addWarning("Collecting areas not yet implemented but gathering " +
1783 cdmBaseStr(gathering) + " has collecting areas.");
1784 }
1785
1786 }
1787
1788 /**
1789 * @param gathering
1790 * @return
1791 */
1792 private String createCollectorString(CdmLightExportState state, GatheringEvent gathering, FieldUnit fieldUnit) {
1793 try {
1794 String collectorString = "";
1795 AgentBase<?> collectorA = CdmBase.deproxy(gathering.getCollector());
1796 if (gathering.getCollector() != null){
1797 if (collectorA instanceof TeamOrPersonBase
1798 && state.getConfig().isHighLightPrimaryCollector()){
1799
1800 Person primaryCollector = fieldUnit.getPrimaryCollector();
1801 if (collectorA instanceof Team){
1802 Team collectorTeam = (Team)collectorA;
1803 boolean isFirst = true;
1804 for (Person member: collectorTeam.getTeamMembers()){
1805 if (!isFirst){
1806 collectorString += "; ";
1807 }
1808 if (member.equals(primaryCollector)){
1809 //highlight
1810 collectorString += "<b>" + member.getTitleCache() + "</b>";
1811 }else{
1812 collectorString += member.getTitleCache();
1813 }
1814 }
1815 }
1816 } else{
1817 collectorString = collectorA.getTitleCache();
1818 }
1819 }
1820 return collectorString;
1821 } catch (Exception e) {
1822 state.getResult().addException(e, "An unexpected error occurred when creating collector string for " +
1823 cdmBaseStr(fieldUnit) + ": " + e.getMessage());
1824 return "";
1825 }
1826 }
1827
1828
1829 /**
1830 * Returns a string representation of the {@link CdmBase cdmBase} object
1831 * for result messages.
1832 */
1833 private String cdmBaseStr(CdmBase cdmBase) {
1834 if (cdmBase == null){
1835 return "-no object available-";
1836 }else{
1837 return cdmBase.getClass().getSimpleName() + ": " + cdmBase.getUuid();
1838 }
1839 }
1840
1841 /**
1842 * {@inheritDoc}
1843 */
1844 @Override
1845 protected boolean doCheck(CdmLightExportState state) {
1846 return false;
1847 }
1848
1849 /**
1850 * {@inheritDoc}
1851 */
1852 @Override
1853 protected boolean isIgnore(CdmLightExportState state) {
1854 return false;
1855 }
1856
1857 }