Project

General

Profile

Download (20.6 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.SQLException;
15
import java.util.Date;
16
import java.util.List;
17
import java.util.Map;
18
import java.util.Set;
19

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

    
25
import eu.etaxonomy.cdm.io.berlinModel.out.mapper.IdMapper;
26
import eu.etaxonomy.cdm.io.berlinModel.out.mapper.MethodMapper;
27
import eu.etaxonomy.cdm.io.common.DbExportStateBase;
28
import eu.etaxonomy.cdm.io.common.Source;
29
import eu.etaxonomy.cdm.model.common.CdmBase;
30
import eu.etaxonomy.cdm.model.common.Extension;
31
import eu.etaxonomy.cdm.model.common.ExtensionType;
32
import eu.etaxonomy.cdm.model.common.Language;
33
import eu.etaxonomy.cdm.model.common.LanguageString;
34
import eu.etaxonomy.cdm.model.description.CommonTaxonName;
35
import eu.etaxonomy.cdm.model.description.DescriptionBase;
36
import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
37
import eu.etaxonomy.cdm.model.description.Distribution;
38
import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
39
import eu.etaxonomy.cdm.model.description.TaxonDescription;
40
import eu.etaxonomy.cdm.model.description.TaxonInteraction;
41
import eu.etaxonomy.cdm.model.description.TextData;
42
import eu.etaxonomy.cdm.model.location.NamedArea;
43
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
44
import eu.etaxonomy.cdm.model.taxon.Taxon;
45

    
46
/**
47
 * The export class for {@link eu.etaxonomy.cdm.model.description.DescriptionElementBase DescriptionElements}.<p>
48
 * Inserts into DataWarehouse database table <code>Note</code>.<p>
49
 * It is divided into two phases:<ul>
50
 * <li>Phase 1:	Export of DescriptionElements as Notes.
51
 * <li>Phase 2:	Export of TaxonName extensions <code>taxComment</code>, <code>fauComment</code> and <code>fauExtraCodes</code> as Notes.</ul>
52
 * @author e.-m.lee
53
 * @date 23.02.2010
54
 *
55
 */
56
@Component
57
public class PesiNoteExport extends PesiExportBase {
58
	private static final Logger logger = Logger.getLogger(PesiNoteExport.class);
59
	private static final Class<? extends CdmBase> standardMethodParameter = DescriptionElementBase.class;
60

    
61
	private static int modCount = 1000;
62
	private static final String dbTableName = "Note";
63
	private static final String pluralString = "Notes";
64
	private static final String parentPluralString = "Taxa";
65

    
66
	public PesiNoteExport() {
67
		super();
68
	}
69

    
70
	/* (non-Javadoc)
71
	 * @see eu.etaxonomy.cdm.io.common.DbExportBase#getStandardMethodParameter()
72
	 */
73
	@Override
74
	public Class<? extends CdmBase> getStandardMethodParameter() {
75
		return standardMethodParameter;
76
	}
77

    
78
	/* (non-Javadoc)
79
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
80
	 */
81
	@Override
82
	protected boolean doCheck(PesiExportState state) {
83
		boolean result = true;
84
		return result;
85
	}
86

    
87
	/* (non-Javadoc)
88
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
89
	 */
90
	@Override
91
	protected void doInvoke(PesiExportState state) {
92
		try {
93
			logger.error("*** Started Making " + pluralString + " ...");
94

    
95
			// Get the limit for objects to save within a single transaction.
96
			int limit = state.getConfig().getLimitSave();
97
			int pageSize = 1000;
98

    
99
			// Calculate the pageNumber
100
			int pageNumber = 1;
101

    
102
			// Stores whether this invoke was successful or not.
103
			boolean success = true;
104
	
105
			// PESI: Clear the database table Note.
106
			doDelete(state);
107
	
108
			// Get specific mappings: (CDM) DescriptionElement -> (PESI) Note
109
			PesiExportMapping mapping = getMapping();
110
	
111
			// Initialize the db mapper
112
			mapping.initialize(state);
113
	
114
			// PESI: Create the Notes
115
			int count = 0;
116
			int pastCount = 0;
117
			TransactionStatus txStatus = null;
118
			List<DescriptionElementBase> list = null;
119
			
120
			// Start transaction
121
			logger.error("PHASE 1...");
122
			txStatus = startTransaction(true);
123
			logger.error("Started new transaction. Fetching some " + pluralString + " (max: " + pageSize + ") ...");
124
			while ((list = getDescriptionService().listDescriptionElements(null, null, null, pageSize, pageNumber, null)).size() > 0) {
125

    
126
				logger.error("Fetched " + list.size() + " " + pluralString + ". Exporting...");
127
				for (DescriptionElementBase description : list) {
128
					
129
					if (getNoteCategoryFk(description) != null) {
130
						doCount(count++, modCount, pluralString);
131
						success &= mapping.invoke(description);
132
					}
133
				}
134

    
135
				// Commit transaction
136
				commitTransaction(txStatus);
137
				logger.error("Committed transaction.");
138
				logger.error("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
139
				pastCount = count;
140
	
141
				// Start transaction
142
				txStatus = startTransaction(true);
143
				logger.error("Started new transaction. Fetching some " + pluralString + " (max: " + pageSize + ") ...");
144
				
145
				// Increment pageNumber
146
				pageNumber++;
147
			}
148
			if (list.size() == 0) {
149
				logger.error("No " + pluralString + " left to fetch.");
150
			}
151
			// Commit transaction
152
			commitTransaction(txStatus);
153
			logger.error("Committed transaction.");
154

    
155
			
156
			logger.error("PHASE 2...");
157
			txStatus = startTransaction(true);
158
			List<TaxonNameBase> taxonNameList = null;
159
			ExtensionType taxCommentExtensionType = (ExtensionType)getTermService().find(PesiTransformer.taxCommentUuid);
160
			ExtensionType fauCommentExtensionType = (ExtensionType)getTermService().find(PesiTransformer.fauCommentUuid);
161
			ExtensionType fauExtraCodesExtensionType = (ExtensionType)getTermService().find(PesiTransformer.fauExtraCodesUuid);
162
			String taxComment = null;
163
			String fauComment = null;
164
			String fauExtraCodes = null;
165
			
166
			Connection connection = state.getConfig().getDestination().getConnection();
167
			logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
168
			while ((taxonNameList = getNameService().list(null, limit, count, null, null)).size() > 0) {
169

    
170
				logger.error("Fetched " + list.size() + " " + parentPluralString + ". Exporting...");
171
				for (TaxonNameBase taxonName : taxonNameList) {
172
					Set<Extension> extensions = taxonName.getExtensions();
173
					for (Extension extension : extensions) {
174
						if (extension.getType().equals(taxCommentExtensionType)) {
175
							taxComment = extension.getValue();
176
							invokeNotes(taxComment, 
177
									PesiTransformer.getNoteCategoryFk(PesiTransformer.taxCommentUuid), 
178
									PesiTransformer.getNoteCategoryCache(PesiTransformer.taxCommentUuid),
179
									null, null, getTaxonFk(taxonName, state),connection);
180
						} else if (extension.getType().equals(fauCommentExtensionType)) {
181
							fauComment = extension.getValue();
182
							invokeNotes(fauComment, 
183
									PesiTransformer.getNoteCategoryFk(PesiTransformer.fauCommentUuid), 
184
									PesiTransformer.getNoteCategoryCache(PesiTransformer.fauCommentUuid),
185
									null, null, getTaxonFk(taxonName, state),connection);
186
						} else if (extension.getType().equals(fauExtraCodesExtensionType)) {
187
							fauExtraCodes = extension.getValue();
188
							invokeNotes(fauExtraCodes, 
189
									PesiTransformer.getNoteCategoryFk(PesiTransformer.fauExtraCodesUuid), 
190
									PesiTransformer.getNoteCategoryCache(PesiTransformer.fauExtraCodesUuid),
191
									null, null, getTaxonFk(taxonName, state),connection);
192
						}
193
					}
194
					
195
					doCount(count++, modCount, pluralString);
196
				}
197

    
198
				// Commit transaction
199
				commitTransaction(txStatus);
200
				logger.error("Committed transaction.");
201
				logger.error("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
202
				pastCount = count;
203

    
204
				// Start transaction
205
				txStatus = startTransaction(true);
206
				logger.error("Started new transaction. Fetching some " + parentPluralString + " first (max: " + limit + ") ...");
207
			}
208
			if (list.size() == 0) {
209
				logger.error("No " + parentPluralString + " left to fetch.");
210
			}
211
			// Commit transaction
212
			commitTransaction(txStatus);
213
			logger.error("Committed transaction.");
214

    
215

    
216
			logger.error("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
217
			
218
			if (!success){
219
				state.setUnsuccessfull();
220
			}
221
			return;
222
		} catch (SQLException e) {
223
			e.printStackTrace();
224
			logger.error(e.getMessage());
225
			state.setUnsuccessfull();
226
		}
227
	}
228

    
229
	/**
230
	 * @param taxComment
231
	 * @param noteCategoryFk
232
	 * @param noteCategoryCache
233
	 * @param object
234
	 * @param object2
235
	 */
236
	private void invokeNotes(String note, Integer noteCategoryFk,
237
			String noteCategoryCache, Integer languageFk, String languageCache, 
238
			Integer taxonFk, Connection connection) {
239
		String notesSql = "UPDATE Note SET Note_1 = ?, NoteCategoryFk = ?, NoteCategoryCache = ?, LanguageFk = ?, LanguageCache = ? WHERE TaxonFk = ?"; 
240
		try {
241
			PreparedStatement notesStmt = connection.prepareStatement(notesSql);
242
			
243
			if (note != null) {
244
				notesStmt.setString(1, note);
245
			} else {
246
				notesStmt.setObject(1, null);
247
			}
248
			
249
			if (noteCategoryFk != null) {
250
				notesStmt.setInt(2, noteCategoryFk);
251
			} else {
252
				notesStmt.setObject(2, null);
253
			}
254
			
255
			if (noteCategoryCache != null) {
256
				notesStmt.setString(3, noteCategoryCache);
257
			} else {
258
				notesStmt.setObject(3, null);
259
			}
260
			
261
			if (languageFk != null) {
262
				notesStmt.setInt(4, languageFk);
263
			} else {
264
				notesStmt.setObject(4, null);
265
			}
266
			
267
			if (languageCache != null) {
268
				notesStmt.setString(5, languageCache);
269
			} else {
270
				notesStmt.setObject(5, null);
271
			}
272
			
273
			if (taxonFk != null) {
274
				notesStmt.setInt(6, taxonFk);
275
			} else {
276
				notesStmt.setObject(6, null);
277
			}
278
			
279
			notesStmt.executeUpdate();
280
		} catch (SQLException e) {
281
			logger.error("Note could not be created: " + note);
282
			e.printStackTrace();
283
		}
284

    
285

    
286
	}
287

    
288
	/**
289
	 * Deletes all entries of database tables related to <code>Note</code>.
290
	 * @param state The PesiExportState
291
	 * @return Whether the delete operation was successful or not.
292
	 */
293
	protected boolean doDelete(PesiExportState state) {
294
		PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
295
		
296
		String sql;
297
		Source destination =  pesiConfig.getDestination();
298

    
299
		// Clear NoteSource
300
		sql = "DELETE FROM NoteSource";
301
		destination.setQuery(sql);
302
		destination.update(sql);
303

    
304
		// Clear Note
305
		sql = "DELETE FROM " + dbTableName;
306
		destination.setQuery(sql);
307
		destination.update(sql);
308
		return true;
309
	}
310

    
311
	/* (non-Javadoc)
312
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
313
	 */
314
	@Override
315
	protected boolean isIgnore(PesiExportState state) {
316
		// TODO Auto-generated method stub
317
		return false;
318
	}
319

    
320
	/**
321
	 * Returns the <code>Note_1</code> attribute.
322
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
323
	 * @return The <code>Note_1</code> attribute.
324
	 * @see MethodMapper
325
	 */
326
	@SuppressWarnings("unused")
327
	private static String getNote_1(DescriptionElementBase descriptionElement) {
328
		String result = null;
329

    
330
		if (descriptionElement.isInstanceOf(TextData.class)) {
331
			TextData textData = CdmBase.deproxy(descriptionElement, TextData.class);
332
			result = textData.getText(Language.DEFAULT());
333
		}
334

    
335
		return result;
336
	}
337

    
338
	/**
339
	 * Returns the <code>Note_2</code> attribute.
340
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
341
	 * @return The <code>Note_2</code> attribute.
342
	 * @see MethodMapper
343
	 */
344
	@SuppressWarnings("unused")
345
	private static String getNote_2(DescriptionElementBase descriptionElement) {
346
		// TODO: extension
347
		return null;
348
	}
349

    
350
	/**
351
	 * Returns the <code>NoteCategoryFk</code> attribute.
352
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
353
	 * @return The <code>NoteCategoryFk</code> attribute.
354
	 * @see MethodMapper
355
	 */
356
	private static Integer getNoteCategoryFk(DescriptionElementBase descriptionElement) {
357
		Integer result = null;
358
		
359
		result = PesiTransformer.textData2NodeCategoryFk(descriptionElement.getFeature());
360

    
361
		return result;
362
	}
363
	
364
	/**
365
	 * Returns the <code>NoteCategoryCache</code> attribute.
366
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
367
	 * @return The <code>NoteCategoryCache</code> attribute.
368
	 * @see MethodMapper
369
	 */
370
	@SuppressWarnings("unused")
371
	private static String getNoteCategoryCache(DescriptionElementBase descriptionElement) {
372
		String result = null;
373

    
374
		if (descriptionElement.isInstanceOf(TextData.class)) {
375
			result = PesiTransformer.textData2NodeCategoryCache(descriptionElement.getFeature());
376
		}
377

    
378
		return result;
379
	}
380

    
381
	/**
382
	 * Returns the <code>LanguageFk</code> attribute.
383
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
384
	 * @return The <code>LanguageFk</code> attribute.
385
	 * @see MethodMapper
386
	 */
387
	@SuppressWarnings("unused")
388
	private static Integer getLanguageFk(DescriptionElementBase descriptionElement) {
389
		Language language = null;
390

    
391
		Map<Language, LanguageString> multilanguageText = null;
392
		if (descriptionElement.isInstanceOf(CommonTaxonName.class)) {
393
			CommonTaxonName commonTaxonName = CdmBase.deproxy(descriptionElement, CommonTaxonName.class);
394
			language = commonTaxonName.getLanguage();
395
		} else if (descriptionElement.isInstanceOf(TextData.class)) {
396
			TextData textData = CdmBase.deproxy(descriptionElement, TextData.class);
397
			multilanguageText = textData.getMultilanguageText();
398
		} else if (descriptionElement.isInstanceOf(IndividualsAssociation.class)) {
399
			IndividualsAssociation individualsAssociation = CdmBase.deproxy(descriptionElement, IndividualsAssociation.class);
400
			multilanguageText = individualsAssociation.getDescription();
401
		} else if (descriptionElement.isInstanceOf(TaxonInteraction.class)) {
402
			TaxonInteraction taxonInteraction = CdmBase.deproxy(descriptionElement, TaxonInteraction.class);
403
			multilanguageText = taxonInteraction.getDescriptions();
404
		} else {
405
			logger.warn("Given descriptionElement is not of appropriate instance. Hence LanguageCache could not be determined: " + descriptionElement.getUuid());
406
		}
407
		
408
		if (multilanguageText != null) {
409
			Set<Language> languages = multilanguageText.keySet();
410

    
411
			// TODO: Think of something more sophisticated than this
412
			if (languages.size() > 0) {
413
				language = languages.iterator().next();
414
			}
415
		}
416

    
417
		return PesiTransformer.language2LanguageId(language);
418
	}
419

    
420
	/**
421
	 * Returns the <code>LanguageCache</code> attribute.
422
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
423
	 * @return The <code>LanguageCache</code> attribute.
424
	 * @see MethodMapper
425
	 */
426
	@SuppressWarnings("unused")
427
	private static String getLanguageCache(DescriptionElementBase descriptionElement) {
428
		Language language = null;
429

    
430
		Map<Language, LanguageString> multilanguageText = null;
431
		if (descriptionElement.isInstanceOf(CommonTaxonName.class)) {
432
			CommonTaxonName commonTaxonName = CdmBase.deproxy(descriptionElement, CommonTaxonName.class);
433
			language = commonTaxonName.getLanguage();
434
		} else if (descriptionElement.isInstanceOf(TextData.class)) {
435
			TextData textData = CdmBase.deproxy(descriptionElement, TextData.class);
436
			multilanguageText = textData.getMultilanguageText();
437
		} else if (descriptionElement.isInstanceOf(IndividualsAssociation.class)) {
438
			IndividualsAssociation individualsAssociation = CdmBase.deproxy(descriptionElement, IndividualsAssociation.class);
439
			multilanguageText = individualsAssociation.getDescription();
440
		} else if (descriptionElement.isInstanceOf(TaxonInteraction.class)) {
441
			TaxonInteraction taxonInteraction = CdmBase.deproxy(descriptionElement, TaxonInteraction.class);
442
			multilanguageText = taxonInteraction.getDescriptions();
443
		} else {
444
			logger.warn("Given descriptionElement is not of appropriate instance. Hence LanguageCache could not be determined: " + descriptionElement.getUuid());
445
		}
446
		
447
		if (multilanguageText != null) {
448
			Set<Language> languages = multilanguageText.keySet();
449

    
450
			// TODO: Think of something more sophisticated than this
451
			if (languages.size() > 0) {
452
				language = languages.iterator().next();
453
			}
454
		}
455

    
456
		return PesiTransformer.language2LanguageCache(language);
457
	}
458

    
459
	/**
460
	 * Returns the <code>Region</code> attribute.
461
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
462
	 * @return The <code>Region</code> attribute.
463
	 * @see MethodMapper
464
	 */
465
	@SuppressWarnings("unused")
466
	private static String getRegion(DescriptionElementBase descriptionElement) {
467
		String result = null;
468
		DescriptionBase inDescription = descriptionElement.getInDescription();
469
		
470
		// Area information are associated to TaxonDescriptions and Distributions.
471
		if (descriptionElement.isInstanceOf(Distribution.class)) {
472
			Distribution distribution = CdmBase.deproxy(descriptionElement, Distribution.class);
473
			result = PesiTransformer.area2AreaCache(distribution.getArea());
474
		} else if (inDescription != null && inDescription.isInstanceOf(TaxonDescription.class)) {
475
			TaxonDescription taxonDescription = CdmBase.deproxy(inDescription, TaxonDescription.class);
476
			Set<NamedArea> namedAreas = taxonDescription.getGeoScopes();
477
			if (namedAreas.size() == 1) {
478
				result = PesiTransformer.area2AreaCache(namedAreas.iterator().next());
479
			} else if (namedAreas.size() > 1) {
480
				logger.warn("This TaxonDescription contains more than one NamedArea: " + taxonDescription.getTitleCache());
481
			}
482
		}
483
		return result;
484
	}
485

    
486
	/**
487
	 * Returns the <code>TaxonFk</code> attribute.
488
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
489
	 * @param state The {@link PesiExportState PesiExportState}.
490
	 * @return The <code>TaxonFk</code> attribute.
491
	 * @see MethodMapper
492
	 */
493
	@SuppressWarnings("unused")
494
	private static Integer getTaxonFk(DescriptionElementBase descriptionElement, DbExportStateBase<?> state) {
495
		Integer result = null;
496
		DescriptionBase inDescription = descriptionElement.getInDescription();
497
		if (inDescription != null && inDescription.isInstanceOf(TaxonDescription.class)) {
498
			TaxonDescription taxonDescription = CdmBase.deproxy(inDescription, TaxonDescription.class);
499
			Taxon taxon = taxonDescription.getTaxon();
500
			result = state.getDbId(taxon.getName());
501
		}
502
		return result;
503
	}
504
	
505
	/**
506
	 * Returns the TaxonFk for a given TaxonName.
507
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
508
	 * @param state The {@link DbExportStateBase DbExportState}.
509
	 * @return
510
	 */
511
	private static Integer getTaxonFk(TaxonNameBase taxonName, DbExportStateBase<?> state) {
512
		return state.getDbId(taxonName);
513
	}
514
	
515
	/**
516
	 * Returns the <code>LastAction</code> attribute.
517
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
518
	 * @return The <code>LastAction</code> attribute.
519
	 * @see MethodMapper
520
	 */
521
	@SuppressWarnings("unused")
522
	private static String getLastAction(DescriptionElementBase descriptionElement) {
523
		// TODO
524
		return null;
525
	}
526

    
527
	/**
528
	 * Returns the <code>LastActionDate</code> attribute.
529
	 * @param descriptionElement The {@link DescriptionElementBase DescriptionElement}.
530
	 * @return The <code>LastActionDate</code> attribute.
531
	 * @see MethodMapper
532
	 */
533
	@SuppressWarnings("unused")
534
	private static DateTime getLastActionDate(DescriptionElementBase descriptionElement) {
535
		DateTime result = null;
536
		return result;
537
	}
538

    
539
	/**
540
	 * Returns the CDM to PESI specific export mappings.
541
	 * @return The {@link PesiExportMapping PesiExportMapping}.
542
	 */
543
	private PesiExportMapping getMapping() {
544
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
545
		
546
		mapping.addMapper(IdMapper.NewInstance("NoteId"));
547
		mapping.addMapper(MethodMapper.NewInstance("Note_1", this));
548
		mapping.addMapper(MethodMapper.NewInstance("Note_2", this));
549
		mapping.addMapper(MethodMapper.NewInstance("NoteCategoryFk", this));
550
		mapping.addMapper(MethodMapper.NewInstance("NoteCategoryCache", this));
551
		mapping.addMapper(MethodMapper.NewInstance("LanguageFk", this));
552
		mapping.addMapper(MethodMapper.NewInstance("LanguageCache", this));
553
		mapping.addMapper(MethodMapper.NewInstance("Region", this));
554
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk", this.getClass(), "getTaxonFk", standardMethodParameter, DbExportStateBase.class));
555
		mapping.addMapper(MethodMapper.NewInstance("LastAction", this));
556
		mapping.addMapper(MethodMapper.NewInstance("LastActionDate", this));
557

    
558
		return mapping;
559
	}
560

    
561
}
(8-8/15)