Project

General

Profile

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

    
11
import java.sql.SQLException;
12
import java.util.ArrayList;
13
import java.util.HashSet;
14
import java.util.List;
15
import java.util.Set;
16

    
17
import org.apache.commons.lang3.StringUtils;
18
import org.apache.log4j.Logger;
19
import org.springframework.stereotype.Component;
20
import org.springframework.transaction.TransactionStatus;
21

    
22
import eu.etaxonomy.cdm.io.common.IExportConfigurator.DO_REFERENCES;
23
import eu.etaxonomy.cdm.io.common.Source;
24
import eu.etaxonomy.cdm.io.common.mapping.out.DbAnnotationMapper;
25
import eu.etaxonomy.cdm.io.common.mapping.out.DbDoiMapper;
26
import eu.etaxonomy.cdm.io.common.mapping.out.DbExtensionMapper;
27
import eu.etaxonomy.cdm.io.common.mapping.out.DbStringMapper;
28
import eu.etaxonomy.cdm.io.common.mapping.out.DbTimePeriodMapper;
29
import eu.etaxonomy.cdm.io.common.mapping.out.IdMapper;
30
import eu.etaxonomy.cdm.io.common.mapping.out.MethodMapper;
31
import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;
32
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
33
import eu.etaxonomy.cdm.model.common.CdmBase;
34
import eu.etaxonomy.cdm.model.common.Extension;
35
import eu.etaxonomy.cdm.model.common.ExtensionType;
36
import eu.etaxonomy.cdm.model.common.IdentifiableSource;
37
import eu.etaxonomy.cdm.model.reference.Reference;
38
import eu.etaxonomy.cdm.model.reference.ReferenceType;
39

    
40
/**
41
 * The export class for {@link eu.etaxonomy.cdm.model.reference.Reference References}.<p>
42
 * Inserts into DataWarehouse database table <code>Source</code>.
43
 *
44
 * @author e.-m.lee
45
 * @since 11.02.2010
46
 */
47
@Component
48
public class PesiSourceExport extends PesiExportBase {
49

    
50
    private static final long serialVersionUID = -3084883718722120651L;
51
    private static final Logger logger = Logger.getLogger(PesiSourceExport.class);
52

    
53
    private static final Class<? extends CdmBase> standardMethodParameter = Reference.class;
54

    
55
	private static int modCount = 1000;
56
	public static final String dbTableName = "Source";
57
	private static final String pluralString = "Sources";
58
	List<Integer> storedSourceIds = new ArrayList<>();
59

    
60
	public PesiSourceExport() {
61
		super();
62
	}
63

    
64
	@Override
65
	public Class<? extends CdmBase> getStandardMethodParameter() {
66
		return standardMethodParameter;
67
	}
68

    
69
	/**
70
	 * Checks whether a sourceId was stored already.
71
	 * @param sourceId
72
	 * @return
73
	 */
74
	protected boolean isStoredSourceId(Integer sourceId) {
75
		if (storedSourceIds.contains(sourceId)) {
76
			return true;
77
		} else {
78
			return false;
79
		}
80
	}
81

    
82
	/**
83
	 * Adds a sourceId to the list of storedSourceIds.
84
	 * @param sourceId
85
	 */
86
	protected void addToStoredSourceIds(Integer sourceId) {
87
		if (! storedSourceIds.contains(sourceId)) {
88
			this.storedSourceIds.add(sourceId);
89
		}
90
	}
91

    
92
	@Override
93
	protected void doInvoke(PesiExportState state) {
94
		try{
95
			logger.info("*** Started Making " + pluralString + " ...");
96

    
97
			PesiExportConfigurator pesiExportConfigurator = state.getConfig();
98

    
99
			// Get the limit for objects to save within a single transaction.
100
			int limit = pesiExportConfigurator.getLimitSave();
101

    
102
			// Stores whether this invoke was successful or not.
103
			boolean success = true ;
104

    
105
			// PESI: Clear the database table Source.
106
			//doDelete(state);  -> done by stored procedure
107

    
108
			// Get specific mappings: (CDM) Reference -> (PESI) Source
109
			PesiExportMapping mapping = getMapping();
110

    
111
			// Initialize the db mapper
112
			mapping.initialize(state);
113

    
114
			// Create the Sources
115
			int count = 0;
116
			int pastCount = 0;
117
			TransactionStatus txStatus = null;
118
			List<Reference> list = null;
119

    
120
//			logger.error("PHASE 1...");
121
			// Start transaction
122
			txStatus = startTransaction(true);
123
			logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
124
			while ((list = getReferenceService().list(null, limit, count, null, null)).size() > 0) {
125

    
126
				logger.debug("Fetched " + list.size() + " " + pluralString + ". Exporting...");
127
				for (Reference reference : list) {
128
					doCount(count++, modCount, pluralString);
129
					success &= mapping.invoke(reference);
130
				}
131

    
132
				// Commit transaction
133
				commitTransaction(txStatus);
134
				logger.debug("Committed transaction.");
135
				logger.info("Exported " + (count - pastCount) + " " + pluralString + ". Total: " + count);
136
				pastCount = count;
137

    
138
				// Start transaction
139
				txStatus = startTransaction(true);
140
				if (logger.isDebugEnabled()) {
141
                    logger.debug("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
142
                }
143
			}
144
			if (list.size() == 0) {
145
				logger.info("No " + pluralString + " left to fetch.");
146
			}
147
			// Commit transaction
148
			commitTransaction(txStatus);
149
			logger.info("Committed transaction.");
150

    
151
			logger.info("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
152

    
153
			if (!success){
154
				state.getResult().addError("An error occurred in PesiSourceExport.invoke");
155
			}
156
			return;
157
		} catch (SQLException e) {
158
			e.printStackTrace();
159
			logger.error(e.getMessage());
160
			state.getResult().addException(e);
161
			return;
162
		}
163
	}
164

    
165
	/**
166
	 * Deletes all entries of database tables related to <code>Source</code>.
167
	 * @param state The {@link PesiExportState PesiExportState}.
168
	 * @return Whether the delete operation was successful or not.
169
	 */
170
	protected boolean doDelete(PesiExportState state) {
171
		PesiExportConfigurator pesiConfig = state.getConfig();
172

    
173
		String sql;
174
		Source destination =  pesiConfig.getDestination();
175

    
176
		// Clear Occurrences
177
		sql = "DELETE FROM Occurrence";
178
		destination.setQuery(sql);
179
		destination.update(sql);
180

    
181
		// Clear Taxa
182
		sql = "DELETE FROM Taxon";
183
		destination.setQuery(sql);
184
		destination.update(sql);
185

    
186
		// Clear Sources
187
		sql = "DELETE FROM " + dbTableName;
188
		destination.setQuery(sql);
189
		destination.update(sql);
190

    
191
		return true;
192
	}
193

    
194
	/**
195
	 * Returns the <code>IMIS_Id</code> attribute.
196
	 * @param reference The {@link Reference Reference}.
197
	 * @return The <code>IMIS_Id</code> attribute.
198
	 * @see MethodMapper
199
	 */
200
	@SuppressWarnings("unused")
201
	private static Integer getIMIS_Id(Reference reference) {
202
		return null;
203
	}
204

    
205
	/**
206
	 * Returns the <code>SourceCategoryFK</code> attribute.
207
	 * @param reference The {@link Reference Reference}.
208
	 * @return The <code>SourceCategoryFK</code> attribute.
209
	 * @see MethodMapper
210
	 */
211
	@SuppressWarnings("unused")
212
	private static Integer getSourceCategoryFK(Reference reference) {
213
		Integer result = null;
214
		try {
215
		    result = PesiTransformer.reference2SourceCategoryFK(reference);
216
		} catch (Exception e) {
217
			e.printStackTrace();
218
		}
219
		return result;
220
	}
221

    
222
	/**
223
	 * Returns the <code>SourceCategoryCache</code> attribute.
224
	 * @param reference The {@link Reference Reference}.
225
	 * @return The <code>SourceCategoryCache</code> attribute.
226
	 * @see MethodMapper
227
	 */
228
	@SuppressWarnings("unused")
229
	private static String getSourceCategoryCache(Reference reference, PesiExportState state) {
230
		return state.getTransformer().getCacheByReference(reference);
231
	}
232

    
233
	/**
234
	 * Returns the <code>Name</code> attribute. The corresponding CDM attribute is <code>title</code>.
235
	 * @param reference The {@link Reference Reference}.
236
	 * @return The <code>Name</code> attribute.
237
	 * @see MethodMapper
238
	 */
239
	@SuppressWarnings("unused")
240
	private static String getName(Reference reference) {
241
		if (reference != null) {
242
		    //TODO performance, maybe getExtensions only if titleCache ends with ... or if it has a minimum size, e.g. > 250 or >795
243
		    String extensionStr = getExtension(reference, ErmsTransformer.uuidExtTruncatedCache);
244
			if (StringUtils.isNotBlank(extensionStr)){
245
			    return extensionStr;
246
			}else{
247
                return reference.getTitleCache(); // was getTitle()
248
            }
249
		} else {
250
			return null;
251
		}
252
	}
253

    
254

    
255
	/**
256
	 * Returns the <code>AuthorString</code> attribute. The corresponding CDM attribute is the <code>titleCache</code> of an <code>authorTeam</code>.
257
	 * @param reference The {@link Reference Reference}.
258
	 * @return The <code>AuthorString</code> attribute.
259
	 * @see MethodMapper
260
	 */
261
	@SuppressWarnings("unused")
262
	private static String getAuthorString(Reference reference) {
263
		String result = null;
264
		Set<Extension> extensions;
265
		try {
266
    		if (reference != null) {
267
    			TeamOrPersonBase<?> team = reference.getAuthorship();
268
    			if (team != null) {
269
    				result = team.getTitleCache();
270
    			}else if (!reference.getExtensions(ErmsTransformer.uuidExtAuthor).isEmpty()){
271
    			    result = reference.getExtensions(ErmsTransformer.uuidExtAuthor).iterator().next();
272
    			}
273
    		}
274
		} catch (Exception e) {
275
			e.printStackTrace();
276
		}
277

    
278
		return result;
279
	}
280

    
281
	/**
282
	 * Returns the <code>NomRefCache</code> attribute. The corresponding CDM attribute is <code>titleCache</code>.
283
	 * @param reference The {@link Reference Reference}.
284
	 * @return The <code>NomRefCache</code> attribute.
285
	 * @see MethodMapper
286
	 */
287
	@SuppressWarnings("unused")
288
	private static String getNomRefCache(Reference reference) {
289
		return null;
290
//		if (reference != null) {
291
//			return reference.getTitleCache();
292
//		} else {
293
//			return null;
294
//		}
295
	}
296

    
297
	/**
298
	 * Returns the <code>RefIdInSource</code> attribute.
299
	 * @param reference The {@link Reference Reference}.
300
	 * @return The <code>RefIdInSource</code> attribute.
301
	 * @see MethodMapper
302
	 */
303
	@SuppressWarnings("unused")
304
	private static String getRefIdInSource(Reference reference) {
305
		String result = null;
306

    
307
		try {
308
		if (reference != null) {
309
			Set<IdentifiableSource> sourceAll = reference.getSources();
310
			Set<IdentifiableSource> sourceCandidates = filterOriginalPesiDbSources(sourceAll);
311

    
312
			if (sourceCandidates.size() == 1) {
313
				result = sourceCandidates.iterator().next().getIdInSource();
314
			} else if (sourceCandidates.size() > 1) {
315
				logger.warn("Reference for RefIdInSource has multiple IdentifiableSources which are candidates for a PESI originalDbSource. RefIdInSource can't be determined correctly and will be left out: " + reference.getUuid() + " (" + reference.getTitleCache() + ")");
316
				int count = 1;
317
//				for (IdentifiableSource source : sources) {
318
//					result += source.getIdInSource();
319
//					if (count < sources.size()) {
320
//						result += "; ";
321
//					}
322
//					count++;
323
//				}
324
			}
325
		}
326
		} catch (Exception e) {
327
			e.printStackTrace();
328
		}
329

    
330
		return result;
331
	}
332

    
333
	private static Set<IdentifiableSource> filterOriginalPesiDbSources(
334
			Set<IdentifiableSource> sourceAll) {
335
		Set<IdentifiableSource> sourceCandidates = new HashSet<IdentifiableSource>();
336
		for (IdentifiableSource source : sourceAll){
337
			if (isOriginalPesiDbSource(source)){
338
				sourceCandidates.add(source);
339
			}
340
		}
341
		return sourceCandidates;
342
	}
343

    
344
	private static boolean isOriginalPesiDbSource(IdentifiableSource source) {
345
		return (source.getCitation() != null) &&
346
				source.getCitation().getType().equals(ReferenceType.Database);
347
	}
348

    
349
	/**
350
	 * Returns the <code>OriginalDB</code> attribute. The corresponding CDM attribute is the <code>titleCache</code> of a <code>citation</code>.
351
	 * @param reference The {@link Reference Reference}.
352
	 * @return The <code>OriginalDB</code> attribute.
353
	 * @see MethodMapper
354
	 */
355
	@SuppressWarnings("unused")
356
	private static String getOriginalDB(Reference reference) {
357
		String result = "";
358

    
359
		try {
360
    		if (reference != null) {
361
    			Set<IdentifiableSource> sourcesAll = reference.getSources();
362
    			Set<IdentifiableSource> sourceCandidates = filterOriginalPesiDbSources(sourcesAll);
363

    
364
    			if (sourceCandidates.size() == 1) {
365
    				Reference citation = sourceCandidates.iterator().next().getCitation();
366
    				if (citation != null) {
367
    					result = PesiTransformer.databaseString2Abbreviation(citation.getTitleCache()); //or just title
368
    				} else {
369
    					logger.warn("OriginalDB can not be determined because the citation of this source is NULL: " + sourceCandidates.iterator().next().getUuid());
370
    				}
371
    			} else if (sourceCandidates.size() > 1) {
372
    				logger.warn("Taxon has multiple IdentifiableSources: " + reference.getUuid() + " (" + reference.getTitleCache() + ")");
373
    				int count = 1;
374
    				for (IdentifiableSource source : sourceCandidates) {
375
    					Reference citation = source.getCitation();
376
    					if (citation != null) {
377
    						result += PesiTransformer.databaseString2Abbreviation(citation.getTitleCache());
378
    						if (count < sourceCandidates.size()) {
379
    							result += "; ";
380
    						}
381
    						count++;
382
    					}
383
    				}
384
    			} else {
385
    				result = null;
386
    			}
387
    		}
388
		} catch (Exception e) {
389
			e.printStackTrace();
390
		}
391

    
392
		return result;
393
	}
394

    
395
    @Override
396
    protected boolean doCheck(PesiExportState state) {
397
        return true;
398
    }
399

    
400
	@Override
401
	protected boolean isIgnore(PesiExportState state) {
402
		return ! state.getConfig().getDoReferences().equals(DO_REFERENCES.ALL);
403
	}
404

    
405
	/**
406
	 * Returns the CDM to PESI specific export mappings.
407
	 * @return The {@link PesiExportMapping PesiExportMapping}.
408
	 */
409
	private PesiExportMapping getMapping() {
410
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
411

    
412
		mapping.addMapper(IdMapper.NewInstance("SourceId"));
413

    
414
		// IMIS_Id
415
		ExtensionType imisExtensionType = (ExtensionType)getTermService().find(ErmsTransformer.uuidExtImis);
416
		if (imisExtensionType != null) {
417
			mapping.addMapper(DbExtensionMapper.NewInstance(imisExtensionType, "IMIS_Id"));
418
		} else {
419
			mapping.addMapper(MethodMapper.NewInstance("IMIS_Id", this));
420
		}
421

    
422
		mapping.addMapper(MethodMapper.NewInstance("SourceCategoryFK", this));
423
		mapping.addMapper(MethodMapper.NewInstance("SourceCategoryCache", this, Reference.class, PesiExportState.class));
424
		mapping.addMapper(MethodMapper.NewInstance("Name", this));
425
		mapping.addMapper(DbStringMapper.NewInstance("referenceAbstract", "Abstract"));
426
		mapping.addMapper(DbStringMapper.NewInstance("title", "Title"));
427
		mapping.addMapper(MethodMapper.NewInstance("AuthorString", this));
428
		mapping.addMapper(DbTimePeriodMapper.NewInstance("datePublished", "RefYear"));
429
		mapping.addMapper(DbDoiMapper.NewInstance("doi", "Doi"));
430

    
431
		mapping.addMapper(MethodMapper.NewInstance("NomRefCache", this));
432
		mapping.addMapper(DbExtensionMapper.NewInstance(ExtensionType.URL(), "Link"));
433
		mapping.addMapper(DbAnnotationMapper.NewInstance((String)null, "Notes"));
434
		mapping.addMapper(MethodMapper.NewInstance("RefIdInSource", this));
435
		mapping.addMapper(MethodMapper.NewInstance("OriginalDB", this));
436

    
437
		return mapping;
438
	}
439
}
(11-11/13)