Project

General

Profile

Download (15.6 KB) Statistics
| Branch: | Revision:
1
/**
2
* Copyright (C) 2007 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

    
10
package eu.etaxonomy.cdm.io.globis;
11

    
12
import java.lang.reflect.Method;
13
import java.sql.ResultSet;
14
import java.sql.SQLException;
15
import java.sql.Timestamp;
16
import java.util.HashSet;
17
import java.util.Set;
18
import java.util.UUID;
19

    
20
import org.apache.commons.lang.StringUtils;
21
import org.apache.log4j.Logger;
22
import org.hibernate.NonUniqueObjectException;
23
import org.joda.time.DateTime;
24

    
25
import eu.etaxonomy.cdm.io.common.CdmImportBase;
26
import eu.etaxonomy.cdm.io.common.ICdmIO;
27
import eu.etaxonomy.cdm.io.common.IImportConfigurator.EDITOR;
28
import eu.etaxonomy.cdm.io.common.IPartitionedIO;
29
import eu.etaxonomy.cdm.io.common.ImportHelper;
30
import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
31
import eu.etaxonomy.cdm.io.common.Source;
32
import eu.etaxonomy.cdm.io.common.mapping.DbImportMapping;
33
import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
34
import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;
35
import eu.etaxonomy.cdm.model.agent.Person;
36
import eu.etaxonomy.cdm.model.agent.Team;
37
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
38
import eu.etaxonomy.cdm.model.common.AnnotatableEntity;
39
import eu.etaxonomy.cdm.model.common.Annotation;
40
import eu.etaxonomy.cdm.model.common.AnnotationType;
41
import eu.etaxonomy.cdm.model.common.CdmBase;
42
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
43
import eu.etaxonomy.cdm.model.common.Language;
44
import eu.etaxonomy.cdm.model.common.User;
45
import eu.etaxonomy.cdm.model.location.Country;
46
import eu.etaxonomy.cdm.model.location.NamedArea;
47
import eu.etaxonomy.cdm.model.name.ZoologicalName;
48
import eu.etaxonomy.cdm.strategy.exceptions.StringNotParsableException;
49
import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
50
import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
51

    
52
/**
53
 * @author a.mueller
54
 * @created 20.03.2008
55
 */
56
public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImportBase<GlobisImportConfigurator, GlobisImportState> implements ICdmIO<GlobisImportState>, IPartitionedIO<GlobisImportState> {
57
	private static final Logger logger = Logger.getLogger(GlobisImportBase.class);
58
	
59
	public static final UUID ID_IN_SOURCE_EXT_UUID = UUID.fromString("23dac094-e793-40a4-bad9-649fc4fcfd44");
60
	
61
	//NAMESPACES
62
	
63
	protected static final String REFERENCE_NAMESPACE = "Literatur";
64
	protected static final String TAXON_NAMESPACE = "current_species";
65
	protected static final String COLLECTION_NAMESPACE = "Collection";
66
	protected static final String IMAGE_NAMESPACE = "Einzelbilder";
67
	protected static final String SPEC_TAX_NAMESPACE = "specTax";
68
	protected static final String TYPE_NAMESPACE = "specTax.SpecTypeDepository";
69
	
70
	private String pluralString;
71
	private String dbTableName;
72
	private Class cdmTargetClass;
73

    
74
	private INonViralNameParser<?> parser = NonViralNameParserImpl.NewInstance();
75

    
76
	
77
	/**
78
	 * @param dbTableName
79
	 * @param dbTableName2 
80
	 */
81
	public GlobisImportBase(String pluralString, String dbTableName, Class<?> cdmTargetClass) {
82
		this.pluralString = pluralString;
83
		this.dbTableName = dbTableName;
84
		this.cdmTargetClass = cdmTargetClass;
85
	}
86

    
87
	protected void doInvoke(GlobisImportState state){
88
		logger.info("start make " + getPluralString() + " ...");
89
		GlobisImportConfigurator config = state.getConfig();
90
		Source source = config.getSource();
91
			
92
		String strIdQuery = getIdQuery();
93
		String strRecordQuery = getRecordQuery(config);
94

    
95
		int recordsPerTransaction = config.getRecordsPerTransaction();
96
		try{
97
			ResultSetPartitioner<GlobisImportState> partitioner = ResultSetPartitioner.NewInstance(source, strIdQuery, strRecordQuery, recordsPerTransaction);
98
			while (partitioner.nextPartition()){
99
				partitioner.doPartition(this, state);
100
			}
101
		} catch (SQLException e) {
102
			logger.error("SQLException:" +  e);
103
			state.setUnsuccessfull();
104
		}
105
		
106
		logger.info("end make " + getPluralString() + " ... " + getSuccessString(true));
107
		return;
108
	}
109

    
110
	/**
111
	 * @param authorAndYear
112
	 * @param zooName
113
	 */
114
	protected void handleAuthorAndYear(String authorAndYear, ZoologicalName zooName, Integer id, GlobisImportState state) {
115
		if (isBlank(authorAndYear)){
116
			return;
117
		}else if ("[Denis & Schifferm\u00FCller], 1775".equals(authorAndYear)){
118
			handleDenisSchiffermueller(zooName, state);
119
			return;
120
		}else{
121
			try {
122
				String doubtfulAuthorAndYear = null;
123
				if(authorAndYear.matches(".+\\,\\s\\[\\d{4}\\].*")){
124
					doubtfulAuthorAndYear = authorAndYear;
125
					authorAndYear = authorAndYear.replace("[", "").replace("]", "");
126
				}
127
				
128
				parser.parseAuthors(zooName, authorAndYear);
129
				deduplicateAuthors(zooName, state);
130
				
131
				if (doubtfulAuthorAndYear != null){
132
					zooName.setAuthorshipCache(doubtfulAuthorAndYear, true);
133
				}
134
				
135
			} catch (StringNotParsableException e) {
136
				logger.warn("Author could not be parsed: " + authorAndYear + " for id "  +id);
137
				zooName.setAuthorshipCache(authorAndYear, true);
138
			}
139
		}
140
	}
141

    
142
	/**
143
	 * @param zooName
144
	 * @param state
145
	 */
146
	private void handleDenisSchiffermueller(ZoologicalName zooName,
147
			GlobisImportState state) {
148
		String teamStr = "Denis & Schifferm\u00FCller";
149
		Team team = state.getTeam(teamStr);
150
		if (team == null){
151
			team = Team.NewInstance();
152
			state.putTeam(teamStr, team);
153
			getAgentService().save(team);
154
		}
155
		zooName.setCombinationAuthorTeam(team);
156
		zooName.setPublicationYear(1775);
157
		zooName.setAuthorshipCache("[Denis & Schifferm\u00FCller], 1775", true);
158
	}
159
	
160

    
161
	private void deduplicateAuthors(ZoologicalName zooName, GlobisImportState state) {
162
		zooName.setCombinationAuthorTeam(getExistingAuthor(zooName.getCombinationAuthorTeam(), state));
163
		zooName.setExCombinationAuthorTeam(getExistingAuthor(zooName.getExCombinationAuthorTeam(), state));
164
		zooName.setBasionymAuthorTeam(getExistingAuthor(zooName.getBasionymAuthorTeam(), state));
165
		zooName.setExBasionymAuthorTeam(getExistingAuthor(zooName.getExBasionymAuthorTeam(), state));
166
	}
167

    
168
	private TeamOrPersonBase<?> getExistingAuthor(INomenclaturalAuthor nomAuthor, GlobisImportState state) {
169
		TeamOrPersonBase<?> author = (TeamOrPersonBase<?>)nomAuthor;
170
		if (author == null){
171
			return null;
172
		}
173
		if (author instanceof Person){
174
			Person person = state.getPerson(author.getTitleCache());
175
			return saveAndDecide(person, author, author.getTitleCache(), state);
176
		}else if (author instanceof Team){
177
			String key = GlobisAuthorImport.makeTeamKey((Team)author, state, getAgentService());
178
			Team existingTeam = state.getTeam(key);
179
			if (existingTeam == null){
180
				Team newTeam = Team.NewInstance();
181
				for (Person member :((Team) author).getTeamMembers()){
182
					Person existingPerson = state.getPerson(member.getTitleCache());
183
					if (existingPerson != null){
184
						try {
185
							getAgentService().update(existingPerson);
186
						} catch (NonUniqueObjectException nuoe){
187
							// person already exists in 
188
							existingPerson = CdmBase.deproxy(getAgentService().find(existingPerson.getUuid()), Person.class);
189
							state.putPerson(existingPerson.getTitleCache(), existingPerson);
190
						} catch (Exception e) {
191
							throw new RuntimeException (e);
192
						}
193
						newTeam.addTeamMember(existingPerson);
194
//						
195
//						logger.warn("newTeam " + newTeam.getId());
196
					}else{
197
						newTeam.addTeamMember(member);
198
					}	
199
				}
200
				author = newTeam;
201
			}
202
			
203
			return saveAndDecide(existingTeam, author, key, state);
204
		}else{
205
			logger.warn("Author type not supported: " + author.getClass().getName());
206
			return author;
207
		}
208
	}
209

    
210
	private TeamOrPersonBase<?> saveAndDecide(TeamOrPersonBase<?> existing, TeamOrPersonBase<?> author, String key, GlobisImportState state) {
211
		if (existing != null){
212
			try {
213
				getAgentService().update(existing);
214
			} catch (NonUniqueObjectException nuoe){
215
				// person already exists in 
216
				existing = CdmBase.deproxy(getAgentService().find(existing.getUuid()), TeamOrPersonBase.class);
217
				putAgent(existing, key, state);
218
			} catch (Exception e) {
219
				throw new RuntimeException (e);
220
			}
221
			return existing;
222
		}else{
223
			getAgentService().save(author);
224
			putAgent(author, key, state);
225
			return author;
226
		}
227
	}
228

    
229
	/**
230
	 * @param author
231
	 * @param key
232
	 * @param state
233
	 */
234
	private void putAgent(TeamOrPersonBase<?> agent, String key, GlobisImportState state) {
235
		if (agent instanceof Team){
236
			state.putTeam(key, (Team)agent);
237
		}else{
238
			state.putPerson(key, (Person)agent);
239
		}
240
	}
241

    
242
	/**
243
	 * @param state
244
	 * @param countryStr
245
	 * @return
246
	 */
247
	protected NamedArea getCountry(GlobisImportState state, String countryStr) {
248
		NamedArea country = Country.getCountryByLabel(countryStr);
249
		if (country == null){
250
			try {
251
				country = (NamedArea)state.getTransformer().getNamedAreaByKey(countryStr);
252
			} catch (UndefinedTransformerMethodException e) {
253
				e.printStackTrace();
254
			}
255
		}
256
		return country;
257
	}
258

    
259
	
260

    
261
	public boolean doPartition(ResultSetPartitioner partitioner, GlobisImportState state) {
262
		boolean success = true ;
263
		Set objectsToSave = new HashSet();
264
		
265
 		DbImportMapping<?, ?> mapping = getMapping();
266
		mapping.initialize(state, cdmTargetClass);
267
		
268
		ResultSet rs = partitioner.getResultSet();
269
		try{
270
			while (rs.next()){
271
				success &= mapping.invoke(rs,objectsToSave);
272
			}
273
		} catch (SQLException e) {
274
			logger.error("SQLException:" +  e);
275
			return false;
276
		}
277
	
278
		partitioner.startDoSave();
279
		getCommonService().save(objectsToSave);
280
		return success;
281
	}
282

    
283

    
284
	
285
	/**
286
	 * @return
287
	 */
288
	protected /*abstract*/ DbImportMapping<?, ?> getMapping(){
289
		return null;
290
	}
291
	
292
	/**
293
	 * @return
294
	 */
295
	protected abstract String getRecordQuery(GlobisImportConfigurator config);
296

    
297
	/**
298
	 * @return
299
	 */
300
	protected String getIdQuery(){
301
		String result = " SELECT id FROM " + getTableName();
302
		return result;
303
	}
304
	
305
	/* (non-Javadoc)
306
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getPluralString()
307
	 */
308
	public String getPluralString(){
309
		return pluralString;
310
	}
311

    
312
	/**
313
	 * @return
314
	 */
315
	protected String getTableName(){
316
		return this.dbTableName;
317
	}
318
	
319
	protected boolean doIdCreatedUpdatedNotes(GlobisImportState state, IdentifiableEntity identifiableEntity, ResultSet rs, long id, String namespace)
320
			throws SQLException{
321
		boolean success = true;
322
		//id
323
		success &= ImportHelper.setOriginalSource(identifiableEntity, state.getTransactionalSourceReference(), id, namespace);
324
		//createdUpdateNotes
325
		success &= doCreatedUpdatedNotes(state, identifiableEntity, rs, namespace);
326
		return success;
327
	}
328
	
329
	
330
	protected boolean doCreatedUpdatedNotes(GlobisImportState state, AnnotatableEntity annotatableEntity, ResultSet rs, String namespace)
331
			throws SQLException{
332

    
333
		GlobisImportConfigurator config = state.getConfig();
334
		Object createdWhen = rs.getObject("Created_When");
335
		String createdWho = rs.getString("Created_Who");
336
		Object updatedWhen = rs.getObject("Updated_When");
337
		String updatedWho = rs.getString("Updated_who");
338
		String notes = rs.getString("notes");
339
		
340
		boolean success  = true;
341
		
342
		//Created When, Who, Updated When Who
343
		if (config.getEditor() == null || config.getEditor().equals(EDITOR.NO_EDITORS)){
344
			//do nothing
345
		}else if (config.getEditor().equals(EDITOR.EDITOR_AS_ANNOTATION)){
346
			String createdAnnotationString = "Berlin Model record was created By: " + String.valueOf(createdWho) + " (" + String.valueOf(createdWhen) + ") ";
347
			if (updatedWhen != null && updatedWho != null){
348
				createdAnnotationString += " and updated By: " + String.valueOf(updatedWho) + " (" + String.valueOf(updatedWhen) + ")";
349
			}
350
			Annotation annotation = Annotation.NewInstance(createdAnnotationString, Language.DEFAULT());
351
			annotation.setCommentator(config.getCommentator());
352
			annotation.setAnnotationType(AnnotationType.TECHNICAL());
353
			annotatableEntity.addAnnotation(annotation);
354
		}else if (config.getEditor().equals(EDITOR.EDITOR_AS_EDITOR)){
355
			User creator = getUser(createdWho, state);
356
			User updator = getUser(updatedWho, state);
357
			DateTime created = getDateTime(createdWhen);
358
			DateTime updated = getDateTime(updatedWhen);
359
			annotatableEntity.setCreatedBy(creator);
360
			annotatableEntity.setUpdatedBy(updator);
361
			annotatableEntity.setCreated(created);
362
			annotatableEntity.setUpdated(updated);
363
		}else {
364
			logger.warn("Editor type not yet implemented: " + config.getEditor());
365
		}
366
		
367
		
368
		//notes
369
		if (StringUtils.isNotBlank(notes)){
370
			String notesString = String.valueOf(notes);
371
			if (notesString.length() > 65530 ){
372
				notesString = notesString.substring(0, 65530) + "...";
373
				logger.warn("Notes string is longer than 65530 and was truncated: " + annotatableEntity);
374
			}
375
			Annotation notesAnnotation = Annotation.NewInstance(notesString, null);
376
			//notesAnnotation.setAnnotationType(AnnotationType.EDITORIAL());
377
			//notes.setCommentator(bmiConfig.getCommentator());
378
			annotatableEntity.addAnnotation(notesAnnotation);
379
		}
380
		return success;
381
	}
382
	
383
	private User getUser(String userString, GlobisImportState state){
384
		if (isBlank(userString)){
385
			return null;
386
		}
387
		userString = userString.trim();
388
		
389
		User user = state.getUser(userString);
390
		if (user == null){
391
			user = getTransformedUser(userString,state);
392
		}
393
		if (user == null){
394
			user = makeNewUser(userString, state);
395
		}
396
		if (user == null){
397
			logger.warn("User is null");
398
		}
399
		return user;
400
	}
401
	
402
	private User getTransformedUser(String userString, GlobisImportState state){
403
		Method method = state.getConfig().getUserTransformationMethod();
404
		if (method == null){
405
			return null;
406
		}
407
		try {
408
			userString = (String)state.getConfig().getUserTransformationMethod().invoke(null, userString);
409
		} catch (Exception e) {
410
			logger.warn("Error when trying to transform userString " +  userString + ". No transformation done.");
411
		}
412
		User user = state.getUser(userString);
413
		return user;
414
	}
415

    
416
	private User makeNewUser(String userString, GlobisImportState state){
417
		String pwd = getPassword(); 
418
		User user = User.NewInstance(userString, pwd);
419
		state.putUser(userString, user);
420
		getUserService().save(user);
421
		logger.info("Added new user: " + userString);
422
		return user;
423
	}
424
	
425
	private String getPassword(){
426
		String result = UUID.randomUUID().toString();
427
		return result;
428
	}
429
	
430
	private DateTime getDateTime(Object timeString){
431
		if (timeString == null){
432
			return null;
433
		}
434
		DateTime dateTime = null;
435
		if (timeString instanceof Timestamp){
436
			Timestamp timestamp = (Timestamp)timeString;
437
			dateTime = new DateTime(timestamp);
438
		}else{
439
			logger.warn("time ("+timeString+") is not a timestamp. Datetime set to current date. ");
440
			dateTime = new DateTime();
441
		}
442
		return dateTime;
443
	}
444
	
445
	
446
	
447
	/**
448
	 * Reads a foreign key field from the result set and adds its value to the idSet.
449
	 * @param rs
450
	 * @param teamIdSet
451
	 * @throws SQLException
452
	 */
453
	protected void handleForeignKey(ResultSet rs, Set<String> idSet, String attributeName)
454
			throws SQLException {
455
		Object idObj = rs.getObject(attributeName);
456
		if (idObj != null){
457
			String id  = String.valueOf(idObj);
458
			idSet.add(id);
459
		}
460
	}
461
	
462
	
463
	
464
	
465
	/**
466
	 * Returns true if i is a multiple of recordsPerTransaction
467
	 * @param i
468
	 * @param recordsPerTransaction
469
	 * @return
470
	 */
471
	protected boolean loopNeedsHandling(int i, int recordsPerLoop) {
472
		startTransaction();
473
		return (i % recordsPerLoop) == 0;
474
	}
475
	
476
	protected void doLogPerLoop(int count, int recordsPerLog, String pluralString){
477
		if ((count % recordsPerLog ) == 0 && count!= 0 ){ logger.info(pluralString + " handled: " + (count));}
478
	}
479
	
480

    
481

    
482
	
483
}
(5-5/10)