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