Project

General

Profile

Download (12.3 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.berlinModel.out.mapper.MethodMapper;
25
import eu.etaxonomy.cdm.io.common.Source;
26
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
27
import eu.etaxonomy.cdm.model.common.CdmBase;
28
import eu.etaxonomy.cdm.model.common.DescriptionElementSource;
29
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
30
import eu.etaxonomy.cdm.model.description.TaxonDescription;
31
import eu.etaxonomy.cdm.model.reference.Reference;
32
import eu.etaxonomy.cdm.model.taxon.Taxon;
33
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
34

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
243
		return occurrenceIds;
244
	}
245

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

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

    
264
	/* (non-Javadoc)
265
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
266
	 */
267
	@Override
268
	protected boolean isIgnore(PesiExportState state) {
269
		// TODO
270
//		return ! state.getConfig().isDoOccurrenceSource();
271
		return false;
272
	}
273

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

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

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

    
343
		return mapping;
344
	}
345

    
346
}
(11-11/15)