Project

General

Profile

Download (14.9 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.EnumSet;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Set;
17

    
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 = 5000;
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
			// Get the limit for objects to save within a single transaction.
98
			int limit = modCount;//pesiExportConfigurator.getLimitSave();
99

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

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

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

    
109
			// Initialize the db mapper
110
			mapping.initialize(state);
111

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

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

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

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

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

    
149
			logger.info("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
150

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

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

    
172
		// Clear Sources
173
		String sql = "DELETE FROM " + dbTableName;
174
		destination.setQuery(sql);
175
		destination.update(sql);
176

    
177
		return true;
178
	}
179

    
180
	/**
181
	 * Returns the <code>IMIS_Id</code> attribute.
182
	 * @param reference The {@link Reference Reference}.
183
	 * @return The <code>IMIS_Id</code> attribute.
184
	 * @see MethodMapper
185
	 */
186
	@SuppressWarnings("unused")
187
	private static Integer getIMIS_Id(Reference reference) {
188
		return null;
189
	}
190

    
191
	/**
192
	 * Returns the <code>SourceCategoryFK</code> attribute.
193
	 * @param reference The {@link Reference Reference}.
194
	 * @return The <code>SourceCategoryFK</code> attribute.
195
	 * @see MethodMapper
196
	 */
197
	@SuppressWarnings("unused")
198
	private static Integer getSourceCategoryFK(Reference reference) {
199
		Integer result = null;
200
		try {
201
		    result = PesiTransformer.reference2SourceCategoryFK(reference);
202
		} catch (Exception e) {
203
			e.printStackTrace();
204
		}
205
		return result;
206
	}
207

    
208
	/**
209
	 * Returns the <code>SourceCategoryCache</code> attribute.
210
	 * @param reference The {@link Reference Reference}.
211
	 * @return The <code>SourceCategoryCache</code> attribute.
212
	 * @see MethodMapper
213
	 */
214
	@SuppressWarnings("unused")
215
	private static String getSourceCategoryCache(Reference reference, PesiExportState state) {
216
		return state.getTransformer().getCacheByReference(reference);
217
	}
218

    
219
	/**
220
	 * Returns the <code>Name</code> attribute. The corresponding CDM attribute is <code>title</code>.
221
	 * @param reference The {@link Reference Reference}.
222
	 * @return The <code>Name</code> attribute.
223
	 * @see MethodMapper
224
	 */
225
	@SuppressWarnings("unused")
226
	private static String getName(Reference reference) {
227
		if (reference != null) {
228
		    String titleCache = reference.getTitleCache();
229
		    //handling copied from DbObjectMapper
230
		    if (titleCache == null || titleCache.length()>250 || titleCache.endsWith("...")){
231
                Set<String> fullCache = reference.getExtensions(ExtensionType.uuidExtNonTruncatedCache);
232
                if (!fullCache.isEmpty()){
233
                    if (fullCache.size()>1){
234
                        logger.warn("Reference has more than 1 'Non truncated cache' extensions. This should not happen. Arbitrary one taken.");
235
                    }
236
                    String value = fullCache.iterator().next();
237
                    if(isNotBlank(value)){
238
                        titleCache = value;
239
                    }
240
                }
241
            }
242
		    return titleCache;
243
		} else {
244
			return null;
245
		}
246
	}
247

    
248

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

    
272
		return result;
273
	}
274

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

    
291
	/**
292
	 * Returns the <code>RefIdInSource</code> attribute.
293
	 * @param reference The {@link Reference Reference}.
294
	 * @return The <code>RefIdInSource</code> attribute.
295
	 * @see MethodMapper
296
	 */
297
	@SuppressWarnings("unused")
298
	private static String getRefIdInSource(Reference reference) {
299
		String result = null;
300

    
301
		try {
302
		if (reference != null) {
303
			Set<IdentifiableSource> sourceAll = reference.getSources();
304
			Set<IdentifiableSource> sourceCandidates = filterOriginalPesiDbSources(sourceAll);
305

    
306
			if (sourceCandidates.size() == 1) {
307
				result = sourceCandidates.iterator().next().getIdInSource();
308
			} else if (sourceCandidates.size() > 1) {
309
				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() + ")");
310
				int count = 1;
311
//				for (IdentifiableSource source : sources) {
312
//					result += source.getIdInSource();
313
//					if (count < sources.size()) {
314
//						result += "; ";
315
//					}
316
//					count++;
317
//				}
318
			}
319
		}
320
		} catch (Exception e) {
321
			e.printStackTrace();
322
		}
323

    
324
		return result;
325
	}
326

    
327
	private static Set<IdentifiableSource> filterOriginalPesiDbSources(
328
			Set<IdentifiableSource> sourceAll) {
329
		Set<IdentifiableSource> sourceCandidates = new HashSet<>();
330
		for (IdentifiableSource source : sourceAll){
331
			if (isOriginalPesiDbSource(source)){
332
				sourceCandidates.add(source);
333
			}
334
		}
335
		return sourceCandidates;
336
	}
337

    
338
	private static boolean isOriginalPesiDbSource(IdentifiableSource source) {
339
		return (source.getCitation() != null) &&
340
				source.getCitation().getType().equals(ReferenceType.Database);
341
	}
342

    
343
	/**
344
	 * Returns the <code>OriginalDB</code> attribute.
345
	 * @param reference The {@link Reference Reference}.
346
	 * @return The <code>OriginalDB</code> attribute.
347
	 * @see MethodMapper
348
	 */
349
	@SuppressWarnings("unused")
350
	private static String getOriginalDB(Reference reference) {
351
	    //TODO may not work for E+M and FauEu as they may not have import sources for all data
352
	    EnumSet<PesiSource> sources  = getSources(reference);
353
	    return PesiTransformer.getOriginalDbBySources(sources);
354

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

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

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

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

    
410
		mapping.addMapper(IdMapper.NewInstance("SourceId"));
411

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

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

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

    
435
		return mapping;
436
	}
437
}
(12-12/14)