Project

General

Profile

Download (15.7 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.location.Country;
45
import eu.etaxonomy.cdm.model.location.NamedArea;
46
import eu.etaxonomy.cdm.model.name.IZoologicalName;
47
import eu.etaxonomy.cdm.model.permission.User;
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
 * @since 20.03.2008
55
 */
56
public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImportBase<GlobisImportConfigurator, GlobisImportState> implements ICdmIO<GlobisImportState>, IPartitionedIO<GlobisImportState> {
57

    
58
    private static final long serialVersionUID = -7813164269152576841L;
59
    private static final Logger logger = Logger.getLogger(GlobisImportBase.class);
60

    
61
	public static final UUID ID_IN_SOURCE_EXT_UUID = UUID.fromString("23dac094-e793-40a4-bad9-649fc4fcfd44");
62

    
63
	//NAMESPACES
64

    
65
	protected static final String REFERENCE_NAMESPACE = "Literatur";
66
	protected static final String TAXON_NAMESPACE = "current_species";
67
	protected static final String COLLECTION_NAMESPACE = "Collection";
68
	protected static final String IMAGE_NAMESPACE = "Einzelbilder";
69
	protected static final String SPEC_TAX_NAMESPACE = "specTax";
70
	protected static final String TYPE_NAMESPACE = "specTax.SpecTypeDepository";
71

    
72
	private final String pluralString;
73
	private final String dbTableName;
74
	private final Class cdmTargetClass;
75

    
76
	private final INonViralNameParser<?> parser = NonViralNameParserImpl.NewInstance();
77

    
78

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

    
89
	@Override
90
    protected void doInvoke(GlobisImportState state){
91
		logger.info("start make " + getPluralString() + " ...");
92
		GlobisImportConfigurator config = state.getConfig();
93
		Source source = config.getSource();
94

    
95
		String strIdQuery = getIdQuery();
96
		String strRecordQuery = getRecordQuery(config);
97

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

    
109
		logger.info("end make " + getPluralString() + " ... " + getSuccessString(true));
110
		return;
111
	}
112

    
113
	/**
114
	 * @param authorAndYear
115
	 * @param zooName
116
	 */
117
	protected void handleAuthorAndYear(String authorAndYear, IZoologicalName zooName, Integer id, GlobisImportState state) {
118
		if (isBlank(authorAndYear)){
119
			return;
120
		}else if ("[Denis & Schifferm\u00FCller], 1775".equals(authorAndYear)){
121
			handleDenisSchiffermueller(zooName, state);
122
			return;
123
		}else{
124
			try {
125
				String doubtfulAuthorAndYear = null;
126
				if(authorAndYear.matches(".+\\,\\s\\[\\d{4}\\].*")){
127
					doubtfulAuthorAndYear = authorAndYear;
128
					authorAndYear = authorAndYear.replace("[", "").replace("]", "");
129
				}
130

    
131
				parser.parseAuthors(zooName, authorAndYear);
132
				deduplicateAuthors(zooName, state);
133

    
134
				if (doubtfulAuthorAndYear != null){
135
					zooName.setAuthorshipCache(doubtfulAuthorAndYear, true);
136
				}
137

    
138
			} catch (StringNotParsableException e) {
139
				logger.warn("Author could not be parsed: " + authorAndYear + " for id "  +id);
140
				zooName.setAuthorshipCache(authorAndYear, true);
141
			}
142
		}
143
	}
144

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

    
163

    
164
	private void deduplicateAuthors(IZoologicalName zooName, GlobisImportState state) {
165
		zooName.setCombinationAuthorship(getExistingAuthor(zooName.getCombinationAuthorship(), state));
166
		zooName.setExCombinationAuthorship(getExistingAuthor(zooName.getExCombinationAuthorship(), state));
167
		zooName.setBasionymAuthorship(getExistingAuthor(zooName.getBasionymAuthorship(), state));
168
		zooName.setExBasionymAuthorship(getExistingAuthor(zooName.getExBasionymAuthorship(), state));
169
	}
170

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

    
206
			return saveAndDecide(existingTeam, author, key, state);
207
		}else{
208
			logger.warn("Author type not supported: " + author.getClass().getName());
209
			return author;
210
		}
211
	}
212

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

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

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

    
262

    
263

    
264
	@Override
265
    public boolean doPartition(ResultSetPartitioner partitioner, GlobisImportState state) {
266
		boolean success = true ;
267
		Set objectsToSave = new HashSet();
268

    
269
 		DbImportMapping<?, ?> mapping = getMapping();
270
		mapping.initialize(state, cdmTargetClass);
271

    
272
		ResultSet rs = partitioner.getResultSet();
273
		try{
274
			while (rs.next()){
275
				success &= mapping.invoke(rs,objectsToSave);
276
			}
277
		} catch (SQLException e) {
278
			logger.error("SQLException:" +  e);
279
			return false;
280
		}
281

    
282
		partitioner.startDoSave();
283
		getCommonService().save(objectsToSave);
284
		return success;
285
	}
286

    
287

    
288

    
289
	/**
290
	 * @return
291
	 */
292
	protected /*abstract*/ DbImportMapping<?, ?> getMapping(){
293
		return null;
294
	}
295

    
296
	/**
297
	 * @return
298
	 */
299
	protected abstract String getRecordQuery(GlobisImportConfigurator config);
300

    
301
	/**
302
	 * @return
303
	 */
304
	protected String getIdQuery(){
305
		String result = " SELECT id FROM " + getTableName();
306
		return result;
307
	}
308

    
309
	/* (non-Javadoc)
310
	 * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getPluralString()
311
	 */
312
	@Override
313
    public String getPluralString(){
314
		return pluralString;
315
	}
316

    
317
	/**
318
	 * @return
319
	 */
320
	protected String getTableName(){
321
		return this.dbTableName;
322
	}
323

    
324
	protected boolean doIdCreatedUpdatedNotes(GlobisImportState state, IdentifiableEntity identifiableEntity, ResultSet rs, long id, String namespace)
325
			throws SQLException{
326
		boolean success = true;
327
		//id
328
		success &= ImportHelper.setOriginalSource(identifiableEntity, state.getTransactionalSourceReference(), id, namespace);
329
		//createdUpdateNotes
330
		success &= doCreatedUpdatedNotes(state, identifiableEntity, rs, namespace);
331
		return success;
332
	}
333

    
334

    
335
	protected boolean doCreatedUpdatedNotes(GlobisImportState state, AnnotatableEntity annotatableEntity, ResultSet rs, String namespace)
336
			throws SQLException{
337

    
338
		GlobisImportConfigurator config = state.getConfig();
339
		Object createdWhen = rs.getObject("Created_When");
340
		String createdWho = rs.getString("Created_Who");
341
		Object updatedWhen = rs.getObject("Updated_When");
342
		String updatedWho = rs.getString("Updated_who");
343
		String notes = rs.getString("notes");
344

    
345
		boolean success  = true;
346

    
347
		//Created When, Who, Updated When Who
348
		if (config.getEditor() == null || config.getEditor().equals(EDITOR.NO_EDITORS)){
349
			//do nothing
350
		}else if (config.getEditor().equals(EDITOR.EDITOR_AS_ANNOTATION)){
351
			String createdAnnotationString = "Berlin Model record was created By: " + String.valueOf(createdWho) + " (" + String.valueOf(createdWhen) + ") ";
352
			if (updatedWhen != null && updatedWho != null){
353
				createdAnnotationString += " and updated By: " + String.valueOf(updatedWho) + " (" + String.valueOf(updatedWhen) + ")";
354
			}
355
			Annotation annotation = Annotation.NewInstance(createdAnnotationString, Language.DEFAULT());
356
			annotation.setCommentator(config.getCommentator());
357
			annotation.setAnnotationType(AnnotationType.TECHNICAL());
358
			annotatableEntity.addAnnotation(annotation);
359
		}else if (config.getEditor().equals(EDITOR.EDITOR_AS_EDITOR)){
360
			User creator = getUser(createdWho, state);
361
			User updator = getUser(updatedWho, state);
362
			DateTime created = getDateTime(createdWhen);
363
			DateTime updated = getDateTime(updatedWhen);
364
			annotatableEntity.setCreatedBy(creator);
365
			annotatableEntity.setUpdatedBy(updator);
366
			annotatableEntity.setCreated(created);
367
			annotatableEntity.setUpdated(updated);
368
		}else {
369
			logger.warn("Editor type not yet implemented: " + config.getEditor());
370
		}
371

    
372

    
373
		//notes
374
		if (StringUtils.isNotBlank(notes)){
375
			String notesString = String.valueOf(notes);
376
			if (notesString.length() > 65530 ){
377
				notesString = notesString.substring(0, 65530) + "...";
378
				logger.warn("Notes string is longer than 65530 and was truncated: " + annotatableEntity);
379
			}
380
			Annotation notesAnnotation = Annotation.NewInstance(notesString, null);
381
			//notesAnnotation.setAnnotationType(AnnotationType.EDITORIAL());
382
			//notes.setCommentator(bmiConfig.getCommentator());
383
			annotatableEntity.addAnnotation(notesAnnotation);
384
		}
385
		return success;
386
	}
387

    
388
	private User getUser(String userString, GlobisImportState state){
389
		if (isBlank(userString)){
390
			return null;
391
		}
392
		userString = userString.trim();
393

    
394
		User user = state.getUser(userString);
395
		if (user == null){
396
			user = getTransformedUser(userString,state);
397
		}
398
		if (user == null){
399
			user = makeNewUser(userString, state);
400
		}
401
		if (user == null){
402
			logger.warn("User is null");
403
		}
404
		return user;
405
	}
406

    
407
	private User getTransformedUser(String userString, GlobisImportState state){
408
		Method method = state.getConfig().getUserTransformationMethod();
409
		if (method == null){
410
			return null;
411
		}
412
		try {
413
			userString = (String)state.getConfig().getUserTransformationMethod().invoke(null, userString);
414
		} catch (Exception e) {
415
			logger.warn("Error when trying to transform userString " +  userString + ". No transformation done.");
416
		}
417
		User user = state.getUser(userString);
418
		return user;
419
	}
420

    
421
	private User makeNewUser(String userString, GlobisImportState state){
422
		String pwd = getPassword();
423
		User user = User.NewInstance(userString, pwd);
424
		state.putUser(userString, user);
425
		getUserService().save(user);
426
		logger.info("Added new user: " + userString);
427
		return user;
428
	}
429

    
430
	private String getPassword(){
431
		String result = UUID.randomUUID().toString();
432
		return result;
433
	}
434

    
435
	private DateTime getDateTime(Object timeString){
436
		if (timeString == null){
437
			return null;
438
		}
439
		DateTime dateTime = null;
440
		if (timeString instanceof Timestamp){
441
			Timestamp timestamp = (Timestamp)timeString;
442
			dateTime = new DateTime(timestamp);
443
		}else{
444
			logger.warn("time ("+timeString+") is not a timestamp. Datetime set to current date. ");
445
			dateTime = new DateTime();
446
		}
447
		return dateTime;
448
	}
449

    
450

    
451

    
452
	/**
453
	 * Reads a foreign key field from the result set and adds its value to the idSet.
454
	 * @param rs
455
	 * @param teamIdSet
456
	 * @throws SQLException
457
	 */
458
	protected void handleForeignKey(ResultSet rs, Set<String> idSet, String attributeName)
459
			throws SQLException {
460
		Object idObj = rs.getObject(attributeName);
461
		if (idObj != null){
462
			String id  = String.valueOf(idObj);
463
			idSet.add(id);
464
		}
465
	}
466

    
467

    
468

    
469

    
470
	/**
471
	 * Returns true if i is a multiple of recordsPerTransaction
472
	 * @param i
473
	 * @param recordsPerTransaction
474
	 * @return
475
	 */
476
	protected boolean loopNeedsHandling(int i, int recordsPerLoop) {
477
		startTransaction();
478
		return (i % recordsPerLoop) == 0;
479
	}
480

    
481
	protected void doLogPerLoop(int count, int recordsPerLog, String pluralString){
482
		if ((count % recordsPerLog ) == 0 && count!= 0 ){ logger.info(pluralString + " handled: " + (count));}
483
	}
484

    
485

    
486

    
487

    
488
}
(5-5/10)