1
|
/**
|
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
|
import java.util.Set;
|
17
|
|
18
|
import org.apache.log4j.Logger;
|
19
|
|
20
|
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
|
21
|
import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeNotSupportedException;
|
22
|
import eu.etaxonomy.cdm.model.common.CdmBase;
|
23
|
import eu.etaxonomy.cdm.model.common.Language;
|
24
|
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
|
25
|
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
|
26
|
import eu.etaxonomy.cdm.model.description.TaxonDescription;
|
27
|
import eu.etaxonomy.cdm.model.name.INonViralName;
|
28
|
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
|
29
|
import eu.etaxonomy.cdm.model.name.TaxonName;
|
30
|
import eu.etaxonomy.cdm.model.name.TextTypeDesignation;
|
31
|
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
|
32
|
import eu.etaxonomy.cdm.model.name.TypeDesignationStatusBase;
|
33
|
import eu.etaxonomy.cdm.model.occurrence.Collection;
|
34
|
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
|
35
|
import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
|
36
|
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
|
37
|
import eu.etaxonomy.cdm.model.taxon.Synonym;
|
38
|
import eu.etaxonomy.cdm.model.taxon.Taxon;
|
39
|
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
|
40
|
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
|
41
|
|
42
|
/**
|
43
|
* @author a.mueller
|
44
|
* @since 20.04.2011
|
45
|
*/
|
46
|
public class DwcaTypesExport extends DwcaDataExportBase {
|
47
|
|
48
|
private static final long serialVersionUID = 8879154738843628476L;
|
49
|
|
50
|
private static final Logger logger = Logger.getLogger(DwcaTypesExport.class);
|
51
|
|
52
|
private static final String ROW_TYPE = "http://rs.gbif.org/terms/1.0/TypesAndSpecimen";
|
53
|
protected static final String fileName = "typesAndSpecimen.txt";
|
54
|
|
55
|
private DwcaMetaDataRecord metaRecord;
|
56
|
|
57
|
|
58
|
/**
|
59
|
* Constructor
|
60
|
*/
|
61
|
public DwcaTypesExport(DwcaTaxExportState state) {
|
62
|
super();
|
63
|
this.ioName = this.getClass().getSimpleName();
|
64
|
metaRecord = new DwcaMetaDataRecord(! IS_CORE, fileName, ROW_TYPE);
|
65
|
state.addMetaRecord(metaRecord);
|
66
|
file = DwcaTaxExportFile.TYPES;
|
67
|
}
|
68
|
|
69
|
@Override
|
70
|
protected void doInvoke(DwcaTaxExportState state){}
|
71
|
|
72
|
/**
|
73
|
* @param state
|
74
|
* @param node
|
75
|
* @throws IOException
|
76
|
* @throws FileNotFoundException
|
77
|
* @throws UnsupportedEncodingException
|
78
|
*/
|
79
|
@Override
|
80
|
protected void handleTaxonNode(DwcaTaxExportState state, TaxonNode node)
|
81
|
throws IOException, FileNotFoundException, UnsupportedEncodingException {
|
82
|
|
83
|
try {
|
84
|
DwcaTaxExportConfigurator config = state.getConfig();
|
85
|
|
86
|
Taxon taxon = CdmBase.deproxy(node.getTaxon());
|
87
|
|
88
|
//TODO use API methods to retrieve all related specimen
|
89
|
|
90
|
//individual associations
|
91
|
Set<TaxonDescription> descriptions = taxon.getDescriptions();
|
92
|
for (TaxonDescription description : descriptions){
|
93
|
for (DescriptionElementBase el : description.getElements()){
|
94
|
if (el.isInstanceOf(IndividualsAssociation.class)){
|
95
|
DwcaTypesRecord record = new DwcaTypesRecord(metaRecord, config);
|
96
|
IndividualsAssociation individualAssociation = CdmBase.deproxy(el, IndividualsAssociation.class);
|
97
|
if (! state.recordExistsUuid(individualAssociation)
|
98
|
&& handleSpecimen(state, record, individualAssociation, null, taxon, config)){
|
99
|
PrintWriter writer = createPrintWriter(state, file);
|
100
|
record.write(state, writer);
|
101
|
state.addExistingRecordUuid(individualAssociation);
|
102
|
}
|
103
|
}
|
104
|
}
|
105
|
}
|
106
|
|
107
|
//type specimen
|
108
|
INonViralName nvn = taxon.getName();
|
109
|
handleTypeName(state, file, taxon, nvn, metaRecord);
|
110
|
for (Synonym synonym : taxon.getSynonyms()){
|
111
|
handleTypeName(state, file, synonym, nvn, metaRecord);
|
112
|
}
|
113
|
|
114
|
//FIXME
|
115
|
//Determinations
|
116
|
|
117
|
} catch (Exception e) {
|
118
|
String message = "Unexpected exception: " + e.getMessage();
|
119
|
state.getResult().addException(e, message);
|
120
|
}finally{
|
121
|
flushWriter(state, file);
|
122
|
}
|
123
|
}
|
124
|
|
125
|
/**
|
126
|
* @param state
|
127
|
* @param writer
|
128
|
* @param taxon
|
129
|
* @param nvn
|
130
|
* @param config
|
131
|
* @return
|
132
|
* @throws IOException
|
133
|
* @throws UnsupportedEncodingException
|
134
|
* @throws FileNotFoundException
|
135
|
*/
|
136
|
private Set<TypeDesignationBase<?>> handleTypeName(DwcaTaxExportState state,
|
137
|
DwcaTaxExportFile file, TaxonBase<?> taxonBase,
|
138
|
INonViralName nvn, DwcaMetaDataRecord metaRecord)
|
139
|
throws FileNotFoundException, UnsupportedEncodingException, IOException {
|
140
|
|
141
|
DwcaTaxExportConfigurator config = state.getConfig();
|
142
|
Set<TypeDesignationBase<?>> designations = nvn.getTypeDesignations();
|
143
|
for (TypeDesignationBase<?> designation:designations){
|
144
|
DwcaTypesRecord record = new DwcaTypesRecord(metaRecord, config);
|
145
|
if (! state.recordExistsUuid(designation)
|
146
|
&& handleType(state, record, designation, taxonBase, config)){
|
147
|
PrintWriter writer = createPrintWriter(state, file);
|
148
|
record.write(state, writer);
|
149
|
state.addExistingRecordUuid(designation);
|
150
|
}
|
151
|
}
|
152
|
return designations;
|
153
|
}
|
154
|
|
155
|
private boolean handleType(DwcaTaxExportState state, DwcaTypesRecord record,
|
156
|
TypeDesignationBase<?> designation, TaxonBase<?> taxonBase,
|
157
|
DwcaTaxExportConfigurator config) {
|
158
|
designation = CdmBase.deproxy(designation);
|
159
|
if (designation instanceof TextTypeDesignation){
|
160
|
return handleTextualType(state, record, (TextTypeDesignation)designation, taxonBase, config);
|
161
|
}else if (designation instanceof TypeDesignationBase){
|
162
|
return handleSpecimen(state, record, null, designation, taxonBase, config);
|
163
|
}else{
|
164
|
throw new RuntimeException ("TypeDesignation type not handled");
|
165
|
}
|
166
|
}
|
167
|
|
168
|
private boolean handleTextualType(DwcaTaxExportState state, DwcaTypesRecord record,
|
169
|
TextTypeDesignation designation, TaxonBase<?> taxonBase,
|
170
|
DwcaTaxExportConfigurator config) {
|
171
|
|
172
|
if (designation == null){
|
173
|
return false;
|
174
|
}
|
175
|
|
176
|
record.setId(taxonBase.getId());
|
177
|
record.setUuid(taxonBase.getUuid());
|
178
|
record.setBibliographicCitation(designation.getPreferredText(Language.DEFAULT()));
|
179
|
|
180
|
//TODO ???
|
181
|
|
182
|
// record.setSource(getSources3(facade.innerDerivedUnit(), config));
|
183
|
// record.setDescriptionSource(source2);
|
184
|
|
185
|
//TODO missing
|
186
|
record.setVerbatimLabel(designation.getPreferredText(Language.DEFAULT()));
|
187
|
|
188
|
return true;
|
189
|
}
|
190
|
|
191
|
private boolean handleSpecimen(DwcaTaxExportState state, DwcaTypesRecord record, IndividualsAssociation individualsAssociation,
|
192
|
TypeDesignationBase<?> designation, TaxonBase<?> taxonBase, DwcaTaxExportConfigurator config) {
|
193
|
|
194
|
TypeDesignationStatusBase<?> status = null;
|
195
|
DerivedUnitFacade facade = null;
|
196
|
if (individualsAssociation != null){
|
197
|
facade = getFacadeFromAssociation(state, individualsAssociation);
|
198
|
}else if (designation != null){
|
199
|
facade = getFacadeFromDesignation(state, designation);
|
200
|
status = designation.getTypeStatus();
|
201
|
}
|
202
|
if (facade == null){
|
203
|
return false;
|
204
|
}
|
205
|
|
206
|
record.setId(taxonBase.getId());
|
207
|
record.setUuid(taxonBase.getUuid());
|
208
|
record.setBibliographicCitation(facade.getTitleCache());
|
209
|
record.setTypeStatus(status);
|
210
|
record.setTypeDesignatedBy( (designation == null || designation.getCitation()==null)? null: designation.getCitation().getTitleCache());
|
211
|
|
212
|
TaxonName scientificName = getScientificName(facade);
|
213
|
if (scientificName != null){
|
214
|
record.setScientificName(scientificName.getTitleCache());
|
215
|
record.setTaxonRank(scientificName.getRank());
|
216
|
}
|
217
|
|
218
|
record.setOccurrenceId(facade.innerDerivedUnit());
|
219
|
Collection collection = facade.getCollection();
|
220
|
if (collection != null){
|
221
|
record.setCollectionCode(collection.getCode());
|
222
|
if (collection.getInstitute() != null){
|
223
|
record.setInstitutionCode(collection.getInstitute().getCode());
|
224
|
}
|
225
|
}
|
226
|
record.setCatalogNumber(facade.getCatalogNumber());
|
227
|
record.setLocality(facade.getLocalityText());
|
228
|
record.setSex(facade.getSex());
|
229
|
record.setRecordedBy(facade.getCollector());
|
230
|
//TODO ???
|
231
|
|
232
|
String source2 = "";
|
233
|
if (individualsAssociation!=null) {
|
234
|
source2 = getSources2(individualsAssociation.getSources(), config);
|
235
|
}
|
236
|
|
237
|
record.setSource(getSources3(facade.innerDerivedUnit(), config));
|
238
|
record.setDescriptionSource(source2);
|
239
|
|
240
|
record.setEventDate(facade.getGatheringPeriod());
|
241
|
//TODO missing
|
242
|
record.setVerbatimLabel(null);
|
243
|
if (facade.getExactLocation() != null){
|
244
|
if (facade.getExactLocation().getLongitude() != null){
|
245
|
// record.setVerbatimLongitude(facade.getExactLocation().getLongitudeSexagesimal().toString());
|
246
|
record.setVerbatimLongitude(facade.getExactLocation().getLongitude().toString());
|
247
|
}
|
248
|
if (facade.getExactLocation().getLatitude() != null){
|
249
|
// record.setVerbatimLatitude(facade.getExactLocation().getLatitudeSexagesimal().toString());
|
250
|
record.setVerbatimLatitude(facade.getExactLocation().getLatitude().toString());
|
251
|
}
|
252
|
if(facade.getExactLocation().getErrorRadius() != null) {
|
253
|
record.setCoordinatesPrecisionOrError(facade.getExactLocation().getErrorRadius().toString());
|
254
|
}
|
255
|
if(facade.getExactLocation().getReferenceSystem() != null) {
|
256
|
record.setCoordinatesSystem(facade.getExactLocation().getReferenceSystem().toString());
|
257
|
}
|
258
|
}
|
259
|
return true;
|
260
|
}
|
261
|
|
262
|
private TaxonName getScientificName(DerivedUnitFacade facade) {
|
263
|
Set<DeterminationEvent> detEvents = facade.getDeterminations();
|
264
|
for (DeterminationEvent detEvent : detEvents){
|
265
|
if (detEvent.getPreferredFlag()== true || detEvents.size()==1){
|
266
|
return detEvent.getTaxon() == null ? null : detEvent.getTaxon().getName();
|
267
|
}
|
268
|
}
|
269
|
return null;
|
270
|
}
|
271
|
|
272
|
private DerivedUnitFacade getFacadeFromDesignation(DwcaTaxExportState state, TypeDesignationBase<?> designation) {
|
273
|
if (designation.isInstanceOf(SpecimenTypeDesignation.class)){
|
274
|
SpecimenTypeDesignation specDesig = CdmBase.deproxy(designation, SpecimenTypeDesignation.class);
|
275
|
try {
|
276
|
DerivedUnit derivedUnit = specDesig.getTypeSpecimen();
|
277
|
if (derivedUnit == null){
|
278
|
return null;
|
279
|
}else{
|
280
|
DerivedUnitFacade facade = DerivedUnitFacade.NewInstance(derivedUnit);
|
281
|
return facade;
|
282
|
}
|
283
|
} catch (DerivedUnitFacadeNotSupportedException e) {
|
284
|
String message = "DerivedUnit is too complex to be handled by facade based darwin core archive export";
|
285
|
state.getResult().addError(message, this, "getFacadeFromAssociation()");
|
286
|
|
287
|
//TODO handle empty records
|
288
|
return null;
|
289
|
}
|
290
|
}else{
|
291
|
return null;
|
292
|
}
|
293
|
}
|
294
|
|
295
|
private DerivedUnitFacade getFacadeFromAssociation(DwcaTaxExportState state, IndividualsAssociation individualsAssociation) {
|
296
|
SpecimenOrObservationBase<?> specimen = individualsAssociation.getAssociatedSpecimenOrObservation();
|
297
|
DerivedUnitFacade facade;
|
298
|
if (specimen == null){
|
299
|
String message = "Individuals association " + individualsAssociation.getId() + " has no associated specimen";
|
300
|
state.getResult().addWarning(message);
|
301
|
return null;
|
302
|
}else if (! specimen.isInstanceOf(DerivedUnit.class)){
|
303
|
String message = "Non DerivedUnit specimen can not yet be handled by this export";
|
304
|
state.getResult().addWarning(message);
|
305
|
//TODO handle empty records
|
306
|
return null;
|
307
|
}else{
|
308
|
DerivedUnit derivedUnit = CdmBase.deproxy(specimen, DerivedUnit.class);
|
309
|
try {
|
310
|
facade = DerivedUnitFacade.NewInstance(derivedUnit);
|
311
|
} catch (DerivedUnitFacadeNotSupportedException e) {
|
312
|
String message = "DerivedUnit is too complex to be handled by facade based darwin core archive export";
|
313
|
state.getResult().addError(message, e);
|
314
|
//TODO handle empty records
|
315
|
return null;
|
316
|
}
|
317
|
}
|
318
|
return facade;
|
319
|
}
|
320
|
|
321
|
@Override
|
322
|
protected boolean doCheck(DwcaTaxExportState state) {
|
323
|
boolean result = true;
|
324
|
logger.warn("No check implemented for " + this.ioName);
|
325
|
return result;
|
326
|
}
|
327
|
|
328
|
@Override
|
329
|
public boolean isIgnore(DwcaTaxExportState state) {
|
330
|
return ! state.getConfig().isDoTypesAndSpecimen();
|
331
|
}
|
332
|
}
|