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