Project

General

Profile

Download (12.5 KB) Statistics
| Branch: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2009 EDIT
4
* European Distributed Institute of Taxonomy 
5
* http://www.e-taxonomy.eu
6
* 
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.cdm.io.pesi.out;
11

    
12
import java.sql.Connection;
13
import java.sql.PreparedStatement;
14
import java.sql.ResultSet;
15
import java.sql.SQLException;
16
import java.util.HashSet;
17
import java.util.List;
18
import java.util.Set;
19

    
20
import org.apache.log4j.Logger;
21
import org.springframework.stereotype.Component;
22
import org.springframework.transaction.TransactionStatus;
23

    
24
import eu.etaxonomy.cdm.io.common.IExportConfigurator.DO_REFERENCES;
25
import eu.etaxonomy.cdm.io.common.Source;
26
import eu.etaxonomy.cdm.io.common.mapping.out.MethodMapper;
27
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
28
import eu.etaxonomy.cdm.model.common.CdmBase;
29
import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
30
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
31
import eu.etaxonomy.cdm.model.description.TaxonDescription;
32
import eu.etaxonomy.cdm.model.reference.Reference;
33
import eu.etaxonomy.cdm.model.taxon.Taxon;
34
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
35

    
36
/**
37
 * The export class for additional information linked to {@link eu.etaxonomy.cdm.model.description.Distribution Distributions} and {@link eu.etaxonomy.cdm.model.common.DescriptionElementSource DescriptionElements}.<p>
38
 * Inserts into DataWarehouse database table <code>OccurrenceSource</code>.
39
 * @author e.-m.lee
40
 * @date 15.03.2010
41
 *
42
 */
43
@Component
44
@SuppressWarnings("unchecked")
45
public class PesiOccurrenceSourceExport extends PesiExportBase {
46
	private static final Logger logger = Logger.getLogger(PesiOccurrenceSourceExport.class);
47
	private static final Class<? extends CdmBase> standardMethodParameter = AnnotatableEntity.class;
48

    
49
	private static int modCount = 1000;
50
	private static final String dbTableName = "OccurrenceSource";
51
	private static final String pluralString = "OccurrenceSources";
52
	private static final String parentPluralString = "Taxa";
53
	private static Taxon taxon = null;
54

    
55
	public PesiOccurrenceSourceExport() {
56
		super();
57
	}
58

    
59
	/* (non-Javadoc)
60
	 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
61
	 */
62
	@Override
63
	public Class<? extends CdmBase> getStandardMethodParameter() {
64
		return standardMethodParameter;
65
	}
66

    
67
	/* (non-Javadoc)
68
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
69
	 */
70
	@Override
71
	protected boolean doCheck(PesiExportState state) {
72
		boolean result = true;
73
		return result;
74
	}
75

    
76
	/* (non-Javadoc)
77
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
78
	 */
79
	@Override
80
	protected void doInvoke(PesiExportState state) {
81
		try {
82
			logger.error("*** Started Making " + pluralString + " ...");
83
	
84
			String occurrenceSql = "Insert into OccurrenceSource (OccurrenceFk, SourceFk, SourceNameCache, OldTaxonName) " +
85
			"values (?, ?, ?, ?)";
86
			Connection con = state.getConfig().getDestination().getConnection();
87
			PreparedStatement stmt = con.prepareStatement(occurrenceSql);
88

    
89
			// Get the limit for objects to save within a single transaction.
90
			int limit = state.getConfig().getLimitSave();
91

    
92
			// Stores whether this invoke was successful or not.
93
			boolean success = true;
94

    
95
			// PESI: Clear the database table OccurrenceSource.
96
			doDelete(state);
97
	
98
			// Get specific mappings: (CDM) ? -> (PESI) OccurrenceSource
99
			PesiExportMapping mapping = getMapping();
100

    
101
			// Initialize the db mapper
102
			mapping.initialize(state);
103

    
104
			// PESI: Create the OccurrenceSource
105
			int count = 0;
106
			int taxonCount = 0;
107
			int pastCount = 0;
108
			TransactionStatus txStatus = null;
109
			List<TaxonBase> list = null;
110
			
111
			// Start transaction
112
			txStatus = startTransaction(true);
113
			logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
114
			while ((list = getTaxonService().list(null, limit, taxonCount, null, null)).size() > 0) {
115

    
116
				logger.error("Fetched " + list.size() + " " + parentPluralString + ".");
117
				taxonCount += list.size();
118
				for (TaxonBase taxonBase : list) {
119
					if (taxonBase.isInstanceOf(Taxon.class)) {
120

    
121
						// Set the current Taxon
122
						taxon = CdmBase.deproxy(taxonBase, Taxon.class);
123

    
124
						// Determine the TaxonDescriptions
125
						Set<TaxonDescription> taxonDescriptions = taxon.getDescriptions();
126

    
127
						// Determine the DescriptionElements (Citations) for the current Taxon
128
						for (TaxonDescription taxonDescription : taxonDescriptions) {
129
							Set<DescriptionElementBase> descriptionElements = taxonDescription.getElements();
130
							for (DescriptionElementBase descriptionElement : descriptionElements) {
131
								Set<DescriptionElementSource> elementSources = descriptionElement.getSources();
132
								
133
								// Focus on descriptionElements with sources.
134
								if (elementSources.size() > 0) {
135
									for (DescriptionElementSource elementSource : elementSources) {
136
										Reference reference = elementSource.getCitation();
137

    
138
										// Citations can be empty (null): Is it wrong data or just a normal case?
139
										if (reference != null) {
140

    
141
											// Lookup sourceFk
142
											Integer sourceFk = getSourceFk(reference, state);
143
											
144
											if (sourceFk != null && ! state.alreadyProcessedSource(sourceFk)) {
145
												doCount(count++, modCount, pluralString);
146
												
147
												// Add to processed sourceFk's since sourceFk's can be scanned more than once.
148
												state.addToProcessedSources(sourceFk);
149
												
150
												// Query the database for all entries in table 'Occurrence' with the sourceFk just determined.
151
												Set<Integer> occurrenceIds = getOccurrenceIds(sourceFk, state);
152
	
153
												// Insert as many entries in database table 'OccurrenceSource' as occurrenceId's were determined.
154
												insertColumns(stmt, reference, sourceFk, occurrenceIds);
155
											}
156

    
157
										}
158
									}
159
								}
160
								
161
							}
162
						}
163
					}
164
				}
165
				
166
				state.clearAlreadyProcessedSources();
167
				
168
				// Commit transaction
169
				commitTransaction(txStatus);
170
				logger.error("Committed transaction.");
171
				logger.error("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
172
				pastCount = count;
173

    
174
				// Start transaction
175
				txStatus = startTransaction(true);
176
				logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
177
			}
178
			if (list.size() == 0) {
179
				logger.error("No " + pluralString + " left to fetch.");
180
			}
181
			
182
			list = null;
183
			// Commit transaction
184
			commitTransaction(txStatus);
185
			logger.error("Committed transaction.");
186
	
187
			logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
188
			if (!success){
189
				state.setUnsuccessfull();
190
			}
191
			return;
192
		} catch (SQLException e) {
193
			e.printStackTrace();
194
			logger.error(e.getMessage());
195
			state.setUnsuccessfull();
196
			return;
197
		}
198
	}
199

    
200
	/**
201
	 * Inserts columns in the database table OccurrenceSource.
202
	 * @param stmt The prepared statement.
203
	 * @param reference {@link Reference Reference}.
204
	 * @param sourceFk The SourceFk.
205
	 * @param occurrenceIds A {@link java.util.Set Set} of OccurrenceId's.
206
	 */
207
	private void insertColumns(PreparedStatement stmt, Reference reference,
208
			Integer sourceFk, Set<Integer> occurrenceIds) {
209
		for (Integer occurrenceId : occurrenceIds) {
210
			try {
211
				stmt.setInt(1, occurrenceId);
212
				stmt.setInt(2, sourceFk);
213
				stmt.setString(3, getSourceNameCache(reference));
214
				stmt.setString(4, null); // TODO: This is the name of the former taxon (accepted taxon as well as synonym) the source was associated to. How can we get a hand on it?
215
				stmt.execute();
216
			} catch (SQLException e) {
217
				logger.error("SQLException during getOccurrenceId invoke.");
218
				e.printStackTrace();
219
			}
220
		}
221
	}
222

    
223
	/**
224
	 * Returns a Set of OccurrenceId's associated to a given SourceFk.
225
	 * @param state The {@link PesiExportState PesiExportState}.
226
	 * @return Existing OccurrenceId's for a given SourceFk.
227
	 */
228
	private static Set<Integer> getOccurrenceIds(Integer sourceFk, PesiExportState state) {
229
		String occurrenceSql = "Select OccurrenceId From Occurrence where SourceFk = ?";
230
		Connection con = state.getConfig().getDestination().getConnection();
231
		PreparedStatement stmt = null;
232
		Set<Integer> occurrenceIds = new HashSet();
233
		
234
		try {
235
			stmt = con.prepareStatement(occurrenceSql);
236
			stmt.setInt(1, sourceFk);
237
			ResultSet resultSet = stmt.executeQuery();
238
			while (resultSet.next()) {
239
				occurrenceIds.add(resultSet.getInt(1));
240
			}
241
		} catch (SQLException e) {
242
			logger.error("SQLException during getOccurrenceId invoke. (2)");
243
			e.printStackTrace();
244
		}
245

    
246
		return occurrenceIds;
247
	}
248

    
249
	/**
250
	 * Deletes all entries of database tables related to <code>OccurrenceSource</code>.
251
	 * @param state The {@link PesiExportState PesiExportState}.
252
	 * @return Whether the delete operation was successful or not.
253
	 */
254
	protected boolean doDelete(PesiExportState state) {
255
		PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
256
		
257
		String sql;
258
		Source destination =  pesiConfig.getDestination();
259

    
260
		// Clear OccurrenceSource
261
		sql = "DELETE FROM " + dbTableName;
262
		destination.setQuery(sql);
263
		destination.update(sql);
264
		return true;
265
	}
266

    
267
	/* (non-Javadoc)
268
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
269
	 */
270
	@Override
271
	protected boolean isIgnore(PesiExportState state) {
272
		return ! ( state.getConfig().isDoOccurrenceSource() && state.getConfig().isDoOccurrence() && state.getConfig().getDoReferences().equals(DO_REFERENCES.ALL));
273
	}
274

    
275
	/**
276
	 * Returns the <code>OccurrenceFk</code> attribute.
277
	 * @param entity An {@link AnnotatableEntity AnnotatableEntity}.
278
	 * @param state The {@link PesiExportState PesiExportState}.
279
	 * @return The <code>OccurrenceFk</code> attribute.
280
	 * @see MethodMapper
281
	 */
282
	@SuppressWarnings("unused")
283
	private static Integer getOccurrenceFk(AnnotatableEntity entity, PesiExportState state) {
284
		Integer result = null;
285
		return result;
286
	}
287
	
288
	/**
289
	 * Returns the <code>SourceFk</code> attribute.
290
	 * @param entity An {@link AnnotatableEntity AnnotatableEntity}.
291
	 * @param state The {@link PesiExportState PesiExportState}.
292
	 * @return The <code>SourceFk</code> attribute.
293
	 * @see MethodMapper
294
	 */
295
	private static Integer getSourceFk(AnnotatableEntity entity, PesiExportState state) {
296
		Integer result = null;
297
		if (state != null && entity != null && entity.isInstanceOf(Reference.class)) {
298
			Reference reference = CdmBase.deproxy(entity, Reference.class);
299
			result = state.getDbId(reference);
300
		}
301
		return result;
302
	}
303
	
304
	/**
305
	 * Returns the <code>SourceNameCache</code> attribute.
306
	 * @param entity An {@link AnnotatableEntity AnnotatableEntity}.
307
	 * @return The <code>SourceNameCache</code> attribute.
308
	 * @see MethodMapper
309
	 */
310
	private static String getSourceNameCache(AnnotatableEntity entity) {
311
		String result = null;
312
		if (entity != null && entity.isInstanceOf(Reference.class)) {
313
			Reference reference = CdmBase.deproxy(entity, Reference.class);
314
			result = reference.getTitle();
315
		}
316
		return result;
317
	}
318
	
319
	/**
320
	 * Returns the <code>OldTaxonName</code> attribute.
321
	 * @param entity An {@link AnnotatableEntity AnnotatableEntity}.
322
	 * @return The <code>OldTaxonName</code> attribute.
323
	 * @see MethodMapper
324
	 */
325
	@SuppressWarnings("unused")
326
	private static String getOldTaxonName(AnnotatableEntity entity) {
327
		// TODO: This is the name of the former taxon (accepted taxon as well as synonym) the source was associated to.
328
		return null;
329
	}
330

    
331
	/**
332
	 * Returns the CDM to PESI specific export mappings.
333
	 * @return The {@link PesiExportMapping PesiExportMapping}.
334
	 */
335
	private PesiExportMapping getMapping() {
336
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
337

    
338
		// These mapping are not used.
339
		mapping.addMapper(MethodMapper.NewInstance("OccurrenceFk", this.getClass(), "getOccurrenceFk", standardMethodParameter, PesiExportState.class));
340
		mapping.addMapper(MethodMapper.NewInstance("SourceFk", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
341
		mapping.addMapper(MethodMapper.NewInstance("SourceNameCache", this));
342
		mapping.addMapper(MethodMapper.NewInstance("OldTaxonName", this));
343

    
344
		return mapping;
345
	}
346

    
347
}
(13-13/17)