Project

General

Profile

Download (15.5 KB) Statistics
| Branch: | Tag: | Revision:
1 51264420 Andreas Müller
/**
2
* Copyright (C) 2007 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
10
package eu.etaxonomy.cdm.io.dwca.out;
11
12
import java.io.FileNotFoundException;
13
import java.io.IOException;
14
import java.io.PrintWriter;
15
import java.io.UnsupportedEncodingException;
16 d2f7f487 Andreas Müller
import java.util.List;
17 51264420 Andreas Müller
import java.util.Set;
18
19
import org.apache.commons.lang.StringUtils;
20
import org.apache.log4j.Logger;
21
22
import eu.etaxonomy.cdm.common.CdmUtils;
23
import eu.etaxonomy.cdm.model.common.Annotation;
24
import eu.etaxonomy.cdm.model.common.AnnotationType;
25
import eu.etaxonomy.cdm.model.common.CdmBase;
26
import eu.etaxonomy.cdm.model.common.RelationshipTermBase;
27
import eu.etaxonomy.cdm.model.name.INonViralName;
28
import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
29
import eu.etaxonomy.cdm.model.name.Rank;
30
import eu.etaxonomy.cdm.model.name.TaxonName;
31
import eu.etaxonomy.cdm.model.reference.Reference;
32
import eu.etaxonomy.cdm.model.taxon.Classification;
33
import eu.etaxonomy.cdm.model.taxon.Synonym;
34
import eu.etaxonomy.cdm.model.taxon.SynonymType;
35
import eu.etaxonomy.cdm.model.taxon.Taxon;
36
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
37
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
38
import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
39
40
/**
41
 * @author a.mueller
42
 * @created 18.04.2011
43
 */
44
public class DwcaTaxonExport extends DwcaDataExportBase {
45
    private static final long serialVersionUID = -3770976064909193441L;
46
47
    private static final Logger logger = Logger.getLogger(DwcaTaxonExport.class);
48
49
	private static final String ROW_TYPE = "http://rs.tdwg.org/dwc/terms/Taxon";
50
	protected static final String fileName = "coreTax.txt";
51
52
	private DwcaMetaDataRecord metaRecord;
53
54
	/**
55
	 * Constructor
56
	 */
57
	public DwcaTaxonExport(DwcaTaxExportState state) {
58
        super();
59
        this.ioName = this.getClass().getSimpleName();
60
        metaRecord = new DwcaMetaDataRecord(IS_CORE, fileName, ROW_TYPE);
61
        state.addMetaRecord(metaRecord);
62 34b6fc0f Andreas Müller
        file = DwcaTaxExportFile.TAXON;
63 51264420 Andreas Müller
	}
64
65
    @Override
66
    protected void doInvoke(DwcaTaxExportState state){}
67
68
    @Override
69
    protected void handleTaxonNode(DwcaTaxExportState state, TaxonNode node)
70
            throws IOException, FileNotFoundException, UnsupportedEncodingException {
71
72
        try {
73
            Taxon taxon = CdmBase.deproxy(node.getTaxon());
74
            DwcaTaxExportConfigurator config = state.getConfig();
75 34b6fc0f Andreas Müller
            DwcaTaxonRecord record = new DwcaTaxonRecord(metaRecord, config);
76 51264420 Andreas Müller
77
            TaxonName name = taxon.getName();
78
            Taxon parent = node.getParent() == null ? null : node.getParent().getTaxon();
79
            TaxonName basionym = name.getBasionym();
80
            Classification classification = node.getClassification();
81
            if (! state.recordExists(file, taxon)){
82
            	handleTaxonBase(state, record, taxon, name, taxon, parent, basionym, classification, null, false, false);
83
            	PrintWriter writer = createPrintWriter(state, file);
84
                record.write(state, writer);
85
            	state.addExistingRecord(file, taxon);
86
            }
87
88
89
            //synonyms
90 3443c007 Andreas Müller
            if (state.getConfig().isDoSynonyms()){
91
                handleSynonyms(state, taxon, file, classification, metaRecord);
92
            }
93 51264420 Andreas Müller
94
            //misapplied names
95 3443c007 Andreas Müller
            if (state.getConfig().isDoMisappliedNames()){
96
                handleMisapplication(state, taxon, file, classification, metaRecord);
97
            }
98
99 51264420 Andreas Müller
        } catch (Exception e) {
100
            String message = "Unexpected exception: " + e.getMessage();
101
            state.getResult().addException(e, message);
102
        }finally{
103
            flushWriter(state, file);
104 7de8dccc Katja Luther
105 51264420 Andreas Müller
        }
106
    }
107
108
109
110 34b6fc0f Andreas Müller
	private void handleSynonyms(DwcaTaxExportState state, Taxon taxon, DwcaTaxExportFile file,
111 51264420 Andreas Müller
	        Classification classification, DwcaMetaDataRecord metaRecord) throws FileNotFoundException, UnsupportedEncodingException, IOException {
112
		for (Synonym synonym :taxon.getSynonyms() ){
113 8f006e1e Andreas Müller
           if (isUnpublished(state.getConfig(), synonym)){
114
               return;
115
           }
116
117
		    DwcaTaxonRecord record = new DwcaTaxonRecord(metaRecord, state.getConfig());
118 51264420 Andreas Müller
			SynonymType type = synonym.getType();
119
			boolean isProParte = synonym.isProParte();
120
			boolean isPartial = synonym.isPartial();
121
			if (type == null){ // should not happen
122
				type = SynonymType.SYNONYM_OF();
123
			}
124
			TaxonName name = synonym.getName();
125
			//????
126
			Taxon parent = null;
127
			TaxonName basionym = name.getBasionym();
128
129
			if (! state.recordExists(file, synonym)){
130
				handleTaxonBase(state, record, synonym, name, taxon, parent, basionym, classification, type, isProParte, isPartial);
131
				PrintWriter writer = createPrintWriter(state, file);
132
				record.write(state, writer);
133
				state.addExistingRecord(file, synonym);
134
			}
135
		}
136
	}
137
138
	private void handleMisapplication(DwcaTaxExportState state, Taxon taxon,
139 34b6fc0f Andreas Müller
	        DwcaTaxExportFile file, Classification classification, DwcaMetaDataRecord metaRecord) throws FileNotFoundException, UnsupportedEncodingException, IOException {
140 51264420 Andreas Müller
		Set<Taxon> misappliedNames = taxon.getMisappliedNames();
141
		for (Taxon misappliedName : misappliedNames ){
142 34b6fc0f Andreas Müller
			DwcaTaxonRecord record = new DwcaTaxonRecord(metaRecord, state.getConfig());
143 51264420 Andreas Müller
			TaxonRelationshipType relType = TaxonRelationshipType.MISAPPLIED_NAME_FOR();
144
			TaxonName name = misappliedName.getName();
145
			//????
146
			Taxon parent = null;
147
			TaxonName basionym = name.getBasionym();
148
149
			if (! state.recordExists(file, misappliedName)){
150
				handleTaxonBase(state, record, misappliedName, name, taxon, parent, basionym, classification,
151
				        relType, false, false);
152
				PrintWriter writer = createPrintWriter(state, file);
153
                record.write(state, writer);
154
				state.addExistingRecord(file, misappliedName);
155
			}
156
		}
157
	}
158
159
	/**
160
	 * @param state
161
	 * @param record
162
	 * @param taxonBase
163
	 * @param name
164
	 * @param acceptedTaxon
165
	 * @param parent
166
	 * @param basionym
167
	 * @param isPartial
168
	 * @param isProParte
169
	 * @param config
170
	 * @param type
171
	 */
172 34b6fc0f Andreas Müller
	private void handleTaxonBase(DwcaTaxExportState state, DwcaTaxonRecord record, TaxonBase<?> taxonBase, TaxonName name,
173 51264420 Andreas Müller
			Taxon acceptedTaxon, Taxon parent, TaxonName basionym, Classification classification,
174
			RelationshipTermBase<?> relType, boolean isProParte, boolean isPartial) {
175
		record.setId(taxonBase.getId());
176
		record.setUuid(taxonBase.getUuid());
177
178
		//maybe wrong as according to the DwC-A documentation only resolvable ids are allowed, this differs from DwC documentation
179
		record.setScientificNameId(name);
180
		record.setScientificName(name.getTitleCache());
181
182
		record.setAcceptedNameUsageId(acceptedTaxon.getUuid());
183
		record.setAcceptedNameUsage(acceptedTaxon.getName() == null? acceptedTaxon.getTitleCache() : acceptedTaxon.getName().getTitleCache());
184
185
		//parentNameUsage
186
		if (parent != null){
187
			record.setParentNameUsageId(parent.getUuid());
188
			record.setParentNameUsage(parent.getTitleCache());
189
		}
190
191
		//originalNameUsage
192
		// ??? - is not a name usage (concept)
193
		if (basionym != null){
194
			//FIXME needs to be a coreID otherwise use string only
195
//			record.setOriginalNameUsageId(basionym.getUuid());
196
			record.setOriginalNameUsageId(null);
197
			record.setOriginalNameUsage(basionym.getTitleCache());
198
		}
199
200
		//nameAccordingTo
201
		Reference sec = taxonBase.getSec();
202
		if (sec == null){
203 801f7c6e Andreas Müller
			String message = "There is a taxon without sec " + taxonBase.getTitleCache() + "(" + taxonBase.getId() + ")";
204 51264420 Andreas Müller
			state.getResult().addWarning(message);
205
		}else{
206
			record.setNameAccordingToId(taxonBase.getSec().getUuid());
207
			record.setNameAccordingTo(taxonBase.getSec().getTitleCache());
208
		}
209
210
		//namePublishedIn
211
		// ??? is not a nameUsage (concept)
212
		if (name.getNomenclaturalReference() != null){
213
			record.setNamePublishedInId(name.getNomenclaturalReference().getUuid());
214
			record.setNamePublishedIn(name.getNomenclaturalReference() == null ? null : name.getNomenclaturalReference().getTitleCache());
215
		}
216
217
		// what is the exact difference to id and acceptedNameUsageId
218
		record.setTaxonConceptId(taxonBase.getUuid());
219
220
		//Classification
221 3429c491 Andreas Müller
		if (state.getConfig().isWithHigherClassification()){
222 d2f7f487 Andreas Müller
			//all classification and rank specific fields are meant to represent the classification
223 3429c491 Andreas Müller
		    handleHigherClassification(state, record, acceptedTaxon, classification);
224 d2f7f487 Andreas Müller
225 51264420 Andreas Müller
			//... higher ranks
226 3429c491 Andreas Müller
//			handleUninomialOrGenus(record, name);
227
//			if (name.getRank() != null &&  name.getRank().equals(Rank.SUBGENUS())){
228
//				record.setSubgenus(name.getNameCache());
229
//			}
230 51264420 Andreas Müller
			//record.setSubgenus(name.getInfraGenericEpithet());
231
		}
232
		if (name.getRank() != null &&  (name.getRank().isSupraGeneric() || name.getRank().isGenus())){
233
			record.setUninomial(name.getGenusOrUninomial());
234
		}else{
235
			record.setGenusPart(name.getGenusOrUninomial());
236
		}
237
		record.setInfraGenericEpithet(name.getInfraGenericEpithet());
238
239
		record.setSpecificEpithet(name.getSpecificEpithet());
240
		record.setInfraspecificEpithet(name.getInfraSpecificEpithet());
241
242
		record.setTaxonRank(name.getRank());
243
		if (name.getRank() != null){
244
			record.setVerbatimTaxonRank(name.getRank().getAbbreviation());
245
		}else{
246
			String message = "No rank available for " + name.getTitleCache() + "(" + name.getId() + ")";
247
			state.getResult().addWarning(message);
248
		}
249
250
		record.setScientificNameAuthorship(name.getAuthorshipCache());
251
252
		// ??? - use for TextData common names?
253
		record.setVernacularName(null);
254
255
		record.setNomenclaturalCode(name.getNameType());
256
		// ??? TODO Misapplied Names, inferred synonyms
257
		handleTaxonomicStatus(record, name, relType, isProParte, isPartial);
258
		handleNomStatus(record, taxonBase, name);
259
260
		// TODO we need to differentiate technical
261
		String taxonRemarks = "";
262
		for (Annotation annotation : taxonBase.getAnnotations()){
263
			if (AnnotationType.EDITORIAL().equals(annotation.getAnnotationType())){
264
				taxonRemarks += CdmUtils.Nz(annotation.getText());
265
			}
266
		}
267
		for (Annotation annotation : name.getAnnotations()){
268
			if (AnnotationType.EDITORIAL().equals(annotation.getAnnotationType())){
269
				taxonRemarks += CdmUtils.Nz(annotation.getText());
270
			}
271
		}
272
		if (StringUtils.isNotBlank(taxonRemarks)){
273
			record.setTaxonRemarks(taxonRemarks);
274
		}
275
276
		// TODO which date is needed here (taxon, name, sec, ... ?)
277
		record.setModified(taxonBase.getUpdated());
278
279
		// ???
280
		record.setLanguage(null);
281
282
		record.setRights(taxonBase.getRights());
283
284
		//TODO
285
		record.setRightsHolder(null);
286
		record.setAccessRights(null);
287
288
		//TODO currently only via default value
289
		record.setBibliographicCitation(null);
290
		record.setInformationWithheld(null);
291
292
		record.setDatasetId(classification);
293
		record.setDatasetName(classification.getTitleCache());
294
295
		//TODO
296
		record.setSource(null);
297
298
		return;
299
	}
300
301
	/**
302 d2f7f487 Andreas Müller
     * @param state
303
     * @param record
304
     * @param taxonBase
305
     * @param classification
306
     */
307
    private void handleHigherClassification(DwcaTaxExportState state, DwcaTaxonRecord record, Taxon taxon,
308
            Classification classification) {
309
        TaxonNode node = taxon.getTaxonNode(classification);
310
        if (node == null){
311
            return;
312
        }
313
        record.setKingdom(nameOf(node.getAncestorOfRank(Rank.KINGDOM())));
314
        record.setPhylum(nameOf(node.getAncestorOfRank(Rank.PHYLUM())));
315
        record.setClazz(nameOf(node.getAncestorOfRank(Rank.CLASS())));
316
        record.setOrder(nameOf(node.getAncestorOfRank(Rank.ORDER())));
317
        record.setFamily(nameOf(node.getAncestorOfRank(Rank.FAMILY())));
318
        record.setGenus(nameOf(node.getAncestorOfRank(Rank.GENUS())));
319 3429c491 Andreas Müller
        record.setSubgenus(nameOf(node.getAncestorOfRank(Rank.SUBGENUS())));
320 d2f7f487 Andreas Müller
        List<TaxonNode> ancestors = node.getAncestorList();
321
        String higherClassification = higherClassificationString(ancestors);
322
        record.setHigherClassification(higherClassification);
323
    }
324
325
    /**
326
     * @param ancestors
327
     */
328
    private String higherClassificationString(List<TaxonNode> ancestors) {
329
        String result = "";
330
        for (TaxonNode node : ancestors){
331
            String nameOfNode = nameOf(node);
332
            if (StringUtils.isBlank(nameOfNode)){
333
                nameOfNode = "-";
334
            }
335
            result = CdmUtils.concat("|", result, nameOfNode);
336
        }
337
        return result;
338
    }
339
340
    /**
341
     * @param ancestorOfRank
342
     * @return
343
     */
344
    private String nameOf(TaxonNode node) {
345
        if (node != null && node.getTaxon()!= null){
346
            Taxon taxon = node.getTaxon();
347 3429c491 Andreas Müller
            TaxonName name = taxon.getName();
348
            if (name!= null){
349
                if (isNotBlank(name.getNameCache())){
350
                    return name.getNameCache();
351
                }else{
352
                    return name.getTitleCache();
353
                }
354 d2f7f487 Andreas Müller
            }else{
355
                return taxon.getTitleCache();
356
            }
357
        }
358
        return null;
359
    }
360
361
    /**
362 51264420 Andreas Müller
	 * @param record
363
	 * @param name
364
	 * @param type
365
	 * @param isPartial
366
	 * @param isProParte
367
	 */
368 34b6fc0f Andreas Müller
	private void handleTaxonomicStatus(DwcaTaxonRecord record,
369 51264420 Andreas Müller
			INonViralName name, RelationshipTermBase<?> type,
370
			boolean isProParte, boolean isPartial) {
371
		if (type == null){
372
			record.setTaxonomicStatus(name.getNomenclaturalCode().acceptedTaxonStatusLabel());
373
		}else{
374
			String status = name.getNomenclaturalCode().synonymStatusLabel();
375
			if (type.equals(SynonymType.HETEROTYPIC_SYNONYM_OF())){
376
				status = "heterotypicSynonym";
377
			}else if(type.equals(SynonymType.HOMOTYPIC_SYNONYM_OF())){
378
				status = "homotypicSynonym";
379
			}else if(type.equals(TaxonRelationshipType.MISAPPLIED_NAME_FOR())){
380
				status = "misapplied";
381
			}
382
			if (isProParte){
383
				status = "proParteSynonym";
384
			}else if (isPartial){
385
				String message = "Partial synonym is not part of the gbif toxonomic status vocabulary";
386
				logger.warn(message);
387
				status = "partialSynonym";
388
			}
389
390
			record.setTaxonomicStatus(status);
391
		}
392
	}
393
394 3429c491 Andreas Müller
//	/**
395
//	 * @param record
396
//	 * @param name
397
//	 */
398
//	private void handleUninomialOrGenus(DwcaTaxonRecord record, INonViralName name) {
399
//		//epitheta
400
//		String firstEpi = name.getGenusOrUninomial();
401
//		if (StringUtils.isNotBlank(firstEpi)){
402
//			Rank rank = name.getRank();
403
//			if (rank != null){
404
//				if (rank.isLower(Rank.GENUS())){
405 51264420 Andreas Müller
//					record.setGenus(firstEpi);
406 3429c491 Andreas Müller
//				}else if (rank.equals(Rank.GENUS())){
407
//					record.setGenus(firstEpi);
408
//				}else if (rank.equals(Rank.KINGDOM())){
409
//					record.setKingdom(firstEpi);
410
//				}else if (rank.equals(Rank.PHYLUM())){
411
//					record.setPhylum(firstEpi);
412
//				}else if (rank.equals(Rank.CLASS())){
413
//					record.setClazz(firstEpi);
414
//				}else if (rank.equals(Rank.ORDER())){
415
//					record.setOrder(firstEpi);
416
//				}else if (rank.equals(Rank.FAMILY())){
417
//					record.setFamily(firstEpi);
418
//				}else{
419
//					// !!!
420
//					String message = "Rank not covered. Set uninomial as genus instead: " + rank.getLabel();
421
//					logger.warn(message);
422
////					record.setGenus(firstEpi);
423
//				}
424
//
425
//			}
426
//		}
427
//	}
428 51264420 Andreas Müller
429
430
	/**
431
	 * @param record
432
	 * @param taxon
433
	 * @param name
434
	 */
435 34b6fc0f Andreas Müller
	private void handleNomStatus(DwcaTaxonRecord record, TaxonBase<?> taxon,
436 51264420 Andreas Müller
			INonViralName name) {
437
		int nStatus = name.getStatus().size();
438
		if (nStatus > 0){
439
			if (name.getStatus().size()> 1){
440
				String warning = "There is more than 1 nomenclatural status ( " + name.getStatus().size()+ "): " + taxon.getTitleCache();
441
				logger.warn(warning);
442
			}
443
			NomenclaturalStatusType status = name.getStatus().iterator().next().getType();
444
			record.setNomenclaturalStatus(status);
445
		}else{
446
			record.setNomenclaturalStatus(null);
447
		}
448
	}
449
450
451
	@Override
452
	protected boolean doCheck(DwcaTaxExportState state) {
453
		boolean result = true;
454
		logger.warn("No check implemented for " + this.ioName);
455
		return result;
456
	}
457
458
459
	@Override
460 3443c007 Andreas Müller
	public boolean isIgnore(DwcaTaxExportState state) {
461 51264420 Andreas Müller
		return ! state.getConfig().isDoTaxa();
462
	}
463
464
}