Project

General

Profile

Download (12.7 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.old;
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.io.pesi.out.PesiExportBase;
28
import eu.etaxonomy.cdm.io.pesi.out.PesiExportConfigurator;
29
import eu.etaxonomy.cdm.io.pesi.out.PesiExportMapping;
30
import eu.etaxonomy.cdm.io.pesi.out.PesiExportState;
31
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
32
import eu.etaxonomy.cdm.model.common.CdmBase;
33
import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
34
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
35
import eu.etaxonomy.cdm.model.description.TaxonDescription;
36
import eu.etaxonomy.cdm.model.reference.Reference;
37
import eu.etaxonomy.cdm.model.taxon.Taxon;
38
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
39

    
40
/**
41
 * 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>
42
 * Inserts into DataWarehouse database table <code>OccurrenceSource</code>.
43
 * @author e.-m.lee
44
 * @date 15.03.2010
45
 *
46
 */
47
@Component
48
@SuppressWarnings("unchecked")
49
public class PesiOccurrenceSourceExport extends PesiExportBase {
50
	private static final Logger logger = Logger.getLogger(PesiOccurrenceSourceExport.class);
51
	private static final Class<? extends CdmBase> standardMethodParameter = AnnotatableEntity.class;
52

    
53
	private static int modCount = 1000;
54
	private static final String dbTableName = "OccurrenceSource";
55
	private static final String pluralString = "OccurrenceSources";
56
	private static final String parentPluralString = "Taxa";
57
	private static Taxon taxon = null;
58

    
59
	public PesiOccurrenceSourceExport() {
60
		super();
61
	}
62

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

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

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

    
93
			// Get the limit for objects to save within a single transaction.
94
			int limit = state.getConfig().getLimitSave();
95

    
96
			// Stores whether this invoke was successful or not.
97
			boolean success = true;
98

    
99
			// PESI: Clear the database table OccurrenceSource.
100
			doDelete(state);
101
	
102
			// Get specific mappings: (CDM) ? -> (PESI) OccurrenceSource
103
			PesiExportMapping mapping = getMapping();
104

    
105
			// Initialize the db mapper
106
			mapping.initialize(state);
107

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

    
120
				logger.error("Fetched " + list.size() + " " + parentPluralString + ".");
121
				taxonCount += list.size();
122
				for (TaxonBase taxonBase : list) {
123
					if (taxonBase.isInstanceOf(Taxon.class)) {
124

    
125
						// Set the current Taxon
126
						taxon = CdmBase.deproxy(taxonBase, Taxon.class);
127

    
128
						// Determine the TaxonDescriptions
129
						Set<TaxonDescription> taxonDescriptions = taxon.getDescriptions();
130

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

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

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

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

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

    
204
	/**
205
	 * Inserts columns in the database table OccurrenceSource.
206
	 * @param stmt The prepared statement.
207
	 * @param reference {@link Reference Reference}.
208
	 * @param sourceFk The SourceFk.
209
	 * @param occurrenceIds A {@link java.util.Set Set} of OccurrenceId's.
210
	 */
211
	private void insertColumns(PreparedStatement stmt, Reference reference,
212
			Integer sourceFk, Set<Integer> occurrenceIds) {
213
		for (Integer occurrenceId : occurrenceIds) {
214
			try {
215
				stmt.setInt(1, occurrenceId);
216
				stmt.setInt(2, sourceFk);
217
				stmt.setString(3, getSourceNameCache(reference));
218
				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?
219
				stmt.execute();
220
			} catch (SQLException e) {
221
				logger.error("SQLException during getOccurrenceId invoke.");
222
				e.printStackTrace();
223
			}
224
		}
225
	}
226

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

    
250
		return occurrenceIds;
251
	}
252

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

    
264
		// Clear OccurrenceSource
265
		sql = "DELETE FROM " + dbTableName;
266
		destination.setQuery(sql);
267
		destination.update(sql);
268
		return true;
269
	}
270

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

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

    
335
	/**
336
	 * Returns the CDM to PESI specific export mappings.
337
	 * @return The {@link PesiExportMapping PesiExportMapping}.
338
	 */
339
	private PesiExportMapping getMapping() {
340
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
341

    
342
		// These mapping are not used.
343
		mapping.addMapper(MethodMapper.NewInstance("OccurrenceFk", this.getClass(), "getOccurrenceFk", standardMethodParameter, PesiExportState.class));
344
		mapping.addMapper(MethodMapper.NewInstance("SourceFk", this.getClass(), "getSourceFk", standardMethodParameter, PesiExportState.class));
345
		mapping.addMapper(MethodMapper.NewInstance("SourceNameCache", this));
346
		mapping.addMapper(MethodMapper.NewInstance("OldTaxonName", this));
347

    
348
		return mapping;
349
	}
350

    
351
}
(6-6/6)