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