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