Project

General

Profile

Download (12.4 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
			// Commit transaction
182
			commitTransaction(txStatus);
183
			logger.error("Committed transaction.");
184
	
185
			logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
186
			if (!success){
187
				state.setUnsuccessfull();
188
			}
189
			return;
190
		} catch (SQLException e) {
191
			e.printStackTrace();
192
			logger.error(e.getMessage());
193
			state.setUnsuccessfull();
194
			return;
195
		}
196
	}
197

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

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

    
244
		return occurrenceIds;
245
	}
246

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

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

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

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

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

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

    
342
		return mapping;
343
	}
344

    
345
}
(13-13/17)