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