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