Project

General

Profile

Download (28.1 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.ArrayList;
16
import java.util.HashMap;
17
import java.util.List;
18
import java.util.Set;
19

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

    
24
import eu.etaxonomy.cdm.io.common.Source;
25
import eu.etaxonomy.cdm.io.common.mapping.out.MethodMapper;
26
import eu.etaxonomy.cdm.model.common.CdmBase;
27
import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
28
import eu.etaxonomy.cdm.model.common.RelationshipBase;
29
import eu.etaxonomy.cdm.model.name.HybridRelationship;
30
import eu.etaxonomy.cdm.model.name.NameRelationship;
31
import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
32
import eu.etaxonomy.cdm.model.name.Rank;
33
import eu.etaxonomy.cdm.model.name.TaxonNameBase;
34
import eu.etaxonomy.cdm.model.taxon.Classification;
35
import eu.etaxonomy.cdm.model.taxon.Synonym;
36
import eu.etaxonomy.cdm.model.taxon.SynonymRelationship;
37
import eu.etaxonomy.cdm.model.taxon.Taxon;
38
import eu.etaxonomy.cdm.model.taxon.TaxonBase;
39
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
40
import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
41

    
42
/**
43
 * The export class for relations between {@link eu.etaxonomy.cdm.model.taxon.TaxonBase TaxonBases}.<p>
44
 * Inserts into DataWarehouse database table <code>RelTaxon</code>.
45
 * @author e.-m.lee
46
 * @date 23.02.2010
47
 *
48
 */
49
@Component
50
public class PesiRelTaxonExport extends PesiExportBase {
51
	private static final Logger logger = Logger.getLogger(PesiRelTaxonExport.class);
52
	private static final Class<? extends CdmBase> standardMethodParameter = RelationshipBase.class;
53

    
54
	private static int modCount = 1000;
55
	private static final String dbTableName = "RelTaxon";
56
	private static final String pluralString = "Relationships";
57
	private static PreparedStatement synonymsStmt;
58
	
59
	private HashMap<Rank, Rank> rank2endRankMap = new HashMap<Rank, Rank>();
60
	private List<Rank> rankList = new ArrayList<Rank>();
61
	private PesiExportMapping mapping;
62
	private int count = 0;
63
	
64
	public PesiRelTaxonExport() {
65
		super();
66
	}
67

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

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

    
85
	
86
	/* (non-Javadoc)
87
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
88
	 */
89
	@Override
90
	protected void doInvoke(PesiExportState state) {
91
		try {
92
			logger.info("*** Started Making " + pluralString + " ...");
93
	
94
			Connection connection = state.getConfig().getDestination().getConnection();
95
			String synonymsSql = "UPDATE Taxon SET KingdomFk = ?, RankFk = ?, RankCache = ? WHERE TaxonId = ?"; 
96
			synonymsStmt = connection.prepareStatement(synonymsSql);
97

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

    
101
			// PESI: Clear the database table RelTaxon.
102
			doDelete(state);
103
	
104
			// Get specific mappings: (CDM) Relationship -> (PESI) RelTaxon
105
			mapping = getMapping();
106

    
107
			// Initialize the db mapper
108
			mapping.initialize(state);
109
			
110
			//Export taxon relations
111
			success &= doPhase01(state, mapping);
112

    
113
			
114
			// Export name relations
115
			success &= doPhase02(state, mapping);
116

    
117
		} catch (SQLException e) {
118
			e.printStackTrace();
119
			logger.error(e.getMessage());
120
			state.setUnsuccessfull();
121
			return;
122
		}
123
	}
124
	
125
	
126
	private boolean doPhase01(PesiExportState state, PesiExportMapping mapping2) throws SQLException {
127
		logger.info("PHASE 1: Taxon Relationships ...");
128
		boolean success = true;
129
		
130
		int limit = state.getConfig().getLimitSave();
131
		// Start transaction
132
		TransactionStatus txStatus = startTransaction(true);
133
		logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
134
		
135
		List<RelationshipBase> list;
136
		
137
		//taxon relations
138
		int partitionCount = 0;
139
		int totalCount = 0;
140
		while ((list = getNextTaxonRelationshipPartition( limit, partitionCount++, null)) != null ) {
141
			totalCount = totalCount + list.size();
142
			logger.info("Read " + list.size() + " PESI relations. Limit: " + limit + ". Total: " + totalCount );
143
//			if (list.size() > 0){
144
//				logger.warn("First relation type is " + list.get(0).getType().getTitleCache());
145
//			}
146
			for (RelationshipBase rel : list){
147
				try {
148
					mapping.invoke(rel);
149
				} catch (Exception e) {
150
					logger.error(e.getMessage() + ". Relationship: " +  rel.getUuid());
151
					e.printStackTrace();
152
				}
153
			}
154
			
155
			commitTransaction(txStatus);
156
			txStatus = startTransaction();
157
		}
158
		list = null;
159
		commitTransaction(txStatus);
160
		return success;
161
	}
162
	
163
	private boolean doPhase02(PesiExportState state, PesiExportMapping mapping2) throws SQLException {
164
		logger.info("PHASE 2: Name Relationships ...");
165
		boolean success = true;
166
		
167
		int limit = state.getConfig().getLimitSave();
168
		// Start transaction
169
		TransactionStatus txStatus = startTransaction(true);
170
		logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
171
		
172
		List<RelationshipBase> list;
173
		
174
		//name relations
175
		int partitionCount = 0;
176
		while ((list = getNextNameRelationshipPartition(null, limit, partitionCount++, null)) != null   ) {
177
			for (RelationshipBase rel : list){
178
				try {
179
					TaxonNameBase<?,?> name1;
180
					TaxonNameBase<?,?> name2;
181
					if (rel.isInstanceOf(HybridRelationship.class)){
182
						HybridRelationship hybridRel = CdmBase.deproxy(rel, HybridRelationship.class);
183
						name1 = hybridRel.getParentName();
184
						name2 = hybridRel.getHybridName();
185
						hybridRel = null;
186
					}else if (rel.isInstanceOf(NameRelationship.class)){
187
						NameRelationship nameRel = CdmBase.deproxy(rel, NameRelationship.class);
188
						name1 = nameRel.getFromName();
189
						name2 = nameRel.getToName();
190
						nameRel = null;
191
					}else{
192
						logger.warn ("Only hybrid- and name-relationships alowed here");
193
						continue;
194
					}
195
					List<IdentifiableEntity> fromList = new ArrayList<IdentifiableEntity>();
196
					List<IdentifiableEntity> toList = new ArrayList<IdentifiableEntity>();
197
					makeList(name1, fromList);
198
					makeList(name2, toList);
199
					
200
					for (IdentifiableEntity fromEntity : fromList){
201
						for (IdentifiableEntity toEntity : toList){
202
							//TODO set entities to state
203
							state.setCurrentFromObject(fromEntity);
204
							state.setCurrentToObject(toEntity);
205
							mapping.invoke(rel);
206
						}
207
					}
208
					fromList = null;
209
					toList = null;
210
					name1 = null;
211
					name2 = null;
212
					rel = null;
213
					commitTransaction(txStatus);
214
					txStatus = startTransaction();
215
					
216
				} catch (Exception e) {
217
					logger.error(e.getMessage() + ". Relationship: " +  rel.getUuid());
218
					e.printStackTrace();
219
				}
220
			}
221
		}
222
		commitTransaction(txStatus);
223
		list = null;
224
		logger.info("End PHASE 2: Name Relationships ...");
225
		state.setCurrentFromObject(null);
226
		state.setCurrentToObject(null);	
227
		return success;
228
	}
229

    
230
	private void makeList(TaxonNameBase<?, ?> name, List<IdentifiableEntity> list) {
231
		if (! hasPesiTaxon(name)){
232
			list.add(name);
233
		}else{
234
			for (TaxonBase taxon:  getPesiTaxa(name)){
235
				list.add(taxon);
236
			}
237
		}
238
	}
239

    
240
	/* (non-Javadoc)
241
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
242
	 */
243
	protected void doInvoke_Old(PesiExportState state) {
244
		try {
245
			logger.info("*** Started Making " + pluralString + " ...");
246
	
247
			Connection connection = state.getConfig().getDestination().getConnection();
248
			String synonymsSql = "UPDATE Taxon SET KingdomFk = ?, RankFk = ?, RankCache = ? WHERE TaxonId = ?"; 
249
			synonymsStmt = connection.prepareStatement(synonymsSql);
250

    
251
			// Stores whether this invoke was successful or not.
252
			boolean success = true;
253

    
254
			// PESI: Clear the database table RelTaxon.
255
			doDelete(state);
256
	
257
			// Get specific mappings: (CDM) Relationship -> (PESI) RelTaxon
258
			mapping = getMapping();
259

    
260
			// Initialize the db mapper
261
			mapping.initialize(state);
262

    
263
			TransactionStatus txStatus = null;
264
			List<Classification> classificationList = null;
265
			
266
			// Specify starting ranks for tree traversing
267
			rankList.add(Rank.KINGDOM());
268
			rankList.add(Rank.GENUS());
269

    
270
			// Specify where to stop traversing (value) when starting at a specific Rank (key)
271
			rank2endRankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
272
			rank2endRankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus
273
			
274
			// Retrieve list of classifications
275
			txStatus = startTransaction(true);
276
			logger.info("Started transaction. Fetching all classifications...");
277
			classificationList = getClassificationService().listClassifications(null, 0, null, null);
278
			commitTransaction(txStatus);
279
			logger.debug("Committed transaction.");
280

    
281
			logger.info("Fetched " + classificationList.size() + " classification(s).");
282

    
283
			for (Classification classification : classificationList) {
284
				for (Rank rank : rankList) {
285
					
286
					txStatus = startTransaction(true);
287
					logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
288

    
289
					List<TaxonNode> rankSpecificRootNodes = getClassificationService().loadRankSpecificRootNodes(classification, rank, null);
290
					logger.info("Fetched " + rankSpecificRootNodes.size() + " RootNodes for Rank " + rank.getLabel());
291

    
292
					commitTransaction(txStatus);
293
					logger.debug("Committed transaction.");
294

    
295
					for (TaxonNode rootNode : rankSpecificRootNodes) {
296
						txStatus = startTransaction(false);
297
						Rank endRank = rank2endRankMap.get(rank);
298
						logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till " + (endRank == null ? "leaves are reached ..." : "Rank " + endRank.getLabel() + " ..."));
299
						
300
						TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
301

    
302
						if (isPesiTaxon(newNode.getTaxon())){
303
							
304
							TaxonNode parentNode = newNode.getParent();
305
	
306
							success &=traverseTree(newNode, parentNode, endRank, state);
307
	
308
							commitTransaction(txStatus);
309
							logger.debug("Committed transaction.");
310
						}else{
311
							logger.debug("Taxon is not in PESI");
312
						}
313

    
314
					}
315
				}
316
			}
317

    
318
			logger.warn("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
319

    
320
			if (!success){
321
				state.setUnsuccessfull();
322
			}
323
			return;
324
		} catch (SQLException e) {
325
			e.printStackTrace();
326
			logger.error(e.getMessage());
327
			state.setUnsuccessfull();
328
			return;
329
		}
330
	}
331

    
332
	/**
333
	 * Traverses the classification recursively and stores determined values for every Taxon.
334
	 * @param childNode
335
	 * @param parentNode
336
	 * @param treeIndex
337
	 * @param fetchLevel
338
	 * @param state
339
	 */
340
	private boolean  traverseTree(TaxonNode childNode, TaxonNode parentNode, Rank fetchLevel, PesiExportState state) {
341
		boolean success = true;
342
		// Traverse all branches from this childNode until specified fetchLevel is reached.
343
		TaxonBase<?> childTaxon = childNode.getTaxon();
344
		if (childTaxon != null) {
345
			if (isPesiTaxon(childTaxon)){
346
				if (childTaxon.getName() != null) {
347
					Rank childTaxonNameRank = childTaxon.getName().getRank();
348
					if (childTaxonNameRank != null) {
349
						if (! childTaxonNameRank.equals(fetchLevel)) {
350
	
351
							success &= saveData(childNode, parentNode, state);
352
	
353
							for (TaxonNode newNode : childNode.getChildNodes()) {
354
								success &= traverseTree(newNode, childNode, fetchLevel, state);
355
							}
356
							
357
						} else {
358
	//						logger.error("Target Rank " + fetchLevel.getLabel() + " reached");
359
							return success;
360
						}
361
					} else {
362
						logger.warn("Rank is NULL. FetchLevel can not be checked: " + childTaxon.getUuid() + " (" + childTaxon.getTitleCache() + ")");
363
					}
364
				} else {
365
					logger.error("TaxonName is NULL for taxon: " + childTaxon.getUuid());
366
				}
367
			}else{
368
				logger.debug("Taxon is not a PESI taxon: " + childTaxon.getUuid());
369
			}
370

    
371
		} else {
372
			logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());
373
		}
374
		return success;
375
	}
376

    
377
	/**
378
	 * Stores values in database for every recursive round.
379
	 * @param childNode
380
	 * @param parentNode
381
	 * @param treeIndex
382
	 * @param state
383
	 * @param currentTaxonFk
384
	 */
385
	private boolean saveData(TaxonNode childNode, TaxonNode parentNode, PesiExportState state) {
386
		boolean success = true;
387
		Taxon childNodeTaxon = childNode.getTaxon();
388
		if (childNodeTaxon != null) {
389
			// TaxonRelationships
390
			success &= saveTaxonRelationships(state, childNodeTaxon);
391
			// TaxonNameRelationships
392
			success &= saveNameRelationships(state, childNodeTaxon);
393
			// SynonymRelationships
394
			success &= saveSynonymAndSynNameRelationships(state, childNodeTaxon);
395
		}
396
		return success;
397
		
398
	}
399

    
400
	private boolean saveSynonymAndSynNameRelationships(PesiExportState state, Taxon childNodeTaxon) {
401
		boolean success = true;
402
		for (SynonymRelationship synRel : childNodeTaxon.getSynonymRelations()) { // synonyms of accepted taxon
403
			Synonym synonym = synRel.getSynonym();
404
			TaxonNameBase<?,?> synonymTaxonName = synonym.getName();
405
			if (! isPesiTaxon(synonym)){
406
				logger.warn("Synonym " + synonym.getId() + " of synonym relation " + synRel.getId() + " is not a PESI taxon. Can't export relationship");
407
				continue;
408
			}
409
			
410
			// Store synonym data in Taxon table
411
			invokeSynonyms(state, synonymTaxonName);
412

    
413
			
414
			
415
			Set<SynonymRelationship> synonymRelations = synonym.getSynonymRelations();
416
			state.setCurrentFromObject(synonym);
417
			for (SynonymRelationship synonymRelationship : synonymRelations) {  //needed? Maybe to make sure that there are no partial synonym relations missed ??
418
				try {
419
					if (neededValuesNotNull(synonymRelationship, state)) {
420
						doCount(count++, modCount, pluralString);
421
						success &= mapping.invoke(synonymRelationship);
422
						
423
					}
424
				} catch (SQLException e) {
425
					logger.error("SynonymRelationship (" + synonymRelationship.getUuid() + ") could not be stored : " + e.getMessage());
426
				}
427
			}
428

    
429
			// SynonymNameRelationship
430
			success &= saveNameRelationships(state, synonym);
431
		}
432
		state.setCurrentFromObject(null);
433
		return success;
434
	}
435

    
436
	private boolean saveNameRelationships(PesiExportState state, TaxonBase taxonBase) {
437
		boolean success = true;
438
		TaxonNameBase<?,?> childNodeTaxonName = taxonBase.getName();
439

    
440
		//from relations
441
		Set<NameRelationship> nameRelations = childNodeTaxonName.getRelationsFromThisName();
442
		state.setCurrentFromObject(taxonBase);
443
		boolean isFrom = true;
444
		success &= saveOneSideNameRelation(state, isFrom, nameRelations);
445
		
446
		//toRelations
447
		nameRelations = childNodeTaxonName.getRelationsToThisName();
448
		state.setCurrentToObject(taxonBase);
449
		isFrom = false;
450
		success &= saveOneSideNameRelation(state, isFrom, nameRelations);
451
		state.setCurrentToObject(null);
452
		return success;
453
	}
454

    
455
	private boolean saveOneSideNameRelation(PesiExportState state, boolean isFrom, Set<NameRelationship> nameRelations) {
456
		boolean success = true;
457
		for (NameRelationship nameRelation : nameRelations) {
458
			try {
459
				TaxonNameBase<?,?> relatedName = isFrom ? nameRelation.getToName(): nameRelation.getFromName();
460
				if ( isPurePesiName(relatedName)){
461
					success &= checkAndInvokeNameRelation(state, nameRelation, relatedName, isFrom);
462
				}else{
463
					for (TaxonBase<?> relatedTaxon : getPesiTaxa(relatedName)){
464
						success &= checkAndInvokeNameRelation(state, nameRelation, relatedTaxon, isFrom);
465
					}
466
				}
467
			} catch (SQLException e) {
468
				logger.error("NameRelationship " + nameRelation.getUuid() + " for " + nameRelation.getFromName().getTitleCache() + " and " + nameRelation.getToName().getTitleCache() + " could not be created: " + e.getMessage());
469
				success = false;
470
			}
471
		}
472
		return success;
473
	}
474

    
475
	private boolean checkAndInvokeNameRelation(PesiExportState state, NameRelationship nameRelation, IdentifiableEntity<?> relatedObject, boolean isFrom) throws SQLException {
476
		boolean success = true;
477
		if (isFrom){
478
			state.setCurrentToObject(relatedObject);
479
		}else{
480
			state.setCurrentFromObject(relatedObject);
481
		}
482
		if (neededValuesNotNull(nameRelation, state)) {
483
			doCount(count++, modCount, pluralString);
484
			success &= mapping.invoke(nameRelation);
485
		}
486
		state.setCurrentFromObject(null);
487
		state.setCurrentToObject(null);
488
		return success;
489
	}
490

    
491
	private boolean saveTaxonRelationships(PesiExportState state, Taxon childNodeTaxon) {
492
		boolean success = true;
493
		Taxon taxon = childNodeTaxon;
494
		Set<TaxonRelationship> taxonRelations = taxon.getRelationsToThisTaxon();
495
		for (TaxonRelationship taxonRelationship : taxonRelations) {
496
			try {
497
				if (neededValuesNotNull(taxonRelationship, state)) {
498
					doCount(count++, modCount, pluralString);
499
					success &= mapping.invoke(taxonRelationship);
500
				}
501
			} catch (SQLException e) {
502
				logger.error("TaxonRelationship could not be created for this TaxonRelation (" + taxonRelationship.getUuid() + "): " + e.getMessage());
503
			}
504
		}
505
		return success;
506
	}
507

    
508
	/**
509
	 * Determines synonym related data and saves them.
510
	 * @param state
511
	 * @param sr
512
	 */
513
	private static void invokeSynonyms(PesiExportState state, TaxonNameBase synonymTaxonName) {
514
		// Store KingdomFk and Rank information in Taxon table
515
		Integer kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(synonymTaxonName.getNomenclaturalCode());
516
		Integer synonymFk = state.getDbId(synonymTaxonName);
517

    
518
		saveSynonymData(synonymTaxonName, synonymTaxonName.getNomenclaturalCode(), kingdomFk, synonymFk);
519
	}
520

    
521
	/**
522
	 * Stores synonym data.
523
	 * @param taxonName
524
	 * @param nomenclaturalCode
525
	 * @param kingdomFk
526
	 * @param synonymParentTaxonFk
527
	 * @param currentTaxonFk
528
	 */
529
	private static boolean saveSynonymData(TaxonNameBase taxonName,
530
			NomenclaturalCode nomenclaturalCode, Integer kingdomFk,
531
			Integer currentSynonymFk) {
532
		try {
533
			if (kingdomFk != null) {
534
				synonymsStmt.setInt(1, kingdomFk);
535
			} else {
536
				synonymsStmt.setObject(1, null);
537
			}
538
			
539
			Integer rankFk = getRankFk(taxonName, nomenclaturalCode);
540
			if (rankFk != null) {
541
				synonymsStmt.setInt(2, rankFk);
542
			} else {
543
				synonymsStmt.setObject(2, null);
544
			}
545
			synonymsStmt.setString(3, getRankCache(taxonName, nomenclaturalCode));
546
			
547
			if (currentSynonymFk != null) {
548
				synonymsStmt.setInt(4, currentSynonymFk);
549
			} else {
550
				synonymsStmt.setObject(4, null);
551
			}
552
			synonymsStmt.executeUpdate();
553
			return true;
554
		} catch (SQLException e) {
555
			logger.error("SQLException during invoke for taxonName - " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + "): " + e.getMessage());
556
			e.printStackTrace();
557
			return false;
558
		}
559
	}
560

    
561
	/**
562
	 * Checks whether needed values for an entity are NULL.
563
	 * @return
564
	 */
565
	private boolean neededValuesNotNull(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
566
		boolean result = true;
567
		if (getTaxonFk1(relationship, state) == null) {
568
			logger.warn("TaxonFk1 is NULL, but is not allowed to be. Therefore no record was written to export database for this relationship: " + relationship.getUuid());
569
			result = false;
570
		}
571
		if (getTaxonFk2(relationship, state) == null) {
572
			logger.warn("TaxonFk2 is NULL, but is not allowed to be. Therefore no record was written to export database for this relationship: " + relationship.getUuid());
573
			result = false;
574
		}
575
		return result;
576
	}
577
	
578
	/**
579
	 * Deletes all entries of database tables related to <code>RelTaxon</code>.
580
	 * @param state The {@link PesiExportState PesiExportState}.
581
	 * @return Whether the delete operation was successful or not.
582
	 */
583
	protected boolean doDelete(PesiExportState state) {
584
		PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
585
		
586
		String sql;
587
		Source destination =  pesiConfig.getDestination();
588

    
589
		// Clear RelTaxon
590
		sql = "DELETE FROM " + dbTableName;
591
		destination.setQuery(sql);
592
		destination.update(sql);
593
		return true;
594
	}
595

    
596
	/* (non-Javadoc)
597
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
598
	 */
599
	@Override
600
	protected boolean isIgnore(PesiExportState state) {
601
		return ! state.getConfig().isDoRelTaxa();
602
	}
603

    
604
	/**
605
	 * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
606
	 * @param relationship The {@link RelationshipBase Relationship}.
607
	 * @param state The {@link PesiExportState PesiExportState}.
608
	 * @return The <code>TaxonFk1</code> attribute.
609
	 * @see MethodMapper
610
	 */
611
	private static Integer getTaxonFk1(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
612
		return getObjectFk(relationship, state, true);
613
	}
614
	
615
	/**
616
	 * Returns the <code>TaxonFk2</code> attribute. It corresponds to a CDM <code>SynonymRelationship</code>.
617
	 * @param relationship The {@link RelationshipBase Relationship}.
618
	 * @param state The {@link PesiExportState PesiExportState}.
619
	 * @return The <code>TaxonFk2</code> attribute.
620
	 * @see MethodMapper
621
	 */
622
	private static Integer getTaxonFk2(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
623
		return getObjectFk(relationship, state, false);
624
	}
625
	
626
	/**
627
	 * Returns the <code>RelTaxonQualifierFk</code> attribute.
628
	 * @param relationship The {@link RelationshipBase Relationship}.
629
	 * @return The <code>RelTaxonQualifierFk</code> attribute.
630
	 * @see MethodMapper
631
	 */
632
	@SuppressWarnings("unused")
633
	private static Integer getRelTaxonQualifierFk(RelationshipBase<?, ?, ?> relationship) {
634
		return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);
635
	}
636
	
637
	/**
638
	 * Returns the <code>RelQualifierCache</code> attribute.
639
	 * @param relationship The {@link RelationshipBase Relationship}.
640
	 * @return The <code>RelQualifierCache</code> attribute.
641
	 * @see MethodMapper
642
	 */
643
	@SuppressWarnings("unused")
644
	private static String getRelQualifierCache(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
645
		String result = null;
646
		NomenclaturalCode code = null;
647
		Taxon taxon = null;
648
		TaxonNameBase name= null;
649
		if (relationship.isInstanceOf(TaxonRelationship.class)){
650
			TaxonRelationship rel = CdmBase.deproxy(relationship, TaxonRelationship.class);
651
			taxon = rel.getToTaxon();
652
			name = taxon.getName();
653
			code = name.getNomenclaturalCode();
654
			rel = null;
655
			
656
		}else if (relationship.isInstanceOf(SynonymRelationship.class)){
657
			SynonymRelationship rel = CdmBase.deproxy(relationship, SynonymRelationship.class);
658
			taxon = rel.getAcceptedTaxon();
659
			name = taxon.getName();
660
			code = name.getNomenclaturalCode();
661
			rel = null;
662

    
663
		}else if (relationship.isInstanceOf(NameRelationship.class)){
664
			NameRelationship rel = CdmBase.deproxy(relationship,  NameRelationship.class);
665
			name = rel.getFromName();
666
			code =name.getNomenclaturalCode();
667
			rel = null;
668
						
669
		}else if (relationship.isInstanceOf(HybridRelationship.class)){
670
			HybridRelationship rel =  CdmBase.deproxy(relationship,  HybridRelationship.class);
671
			name = rel.getParentName();
672
			code = name.getNomenclaturalCode();
673
			rel = null;
674
		}
675
		taxon = null;
676
		name = null;
677
		if (code != null) {
678
			result = state.getConfig().getTransformer().getCacheByRelationshipType(relationship, code);
679
		} else {
680
			logger.error("NomenclaturalCode is NULL while creating the following relationship: " + relationship.getUuid());
681
		}
682
		return result;
683
	}
684
	
685
	/**
686
	 * Returns the <code>Notes</code> attribute.
687
	 * @param relationship The {@link RelationshipBase Relationship}.
688
	 * @return The <code>Notes</code> attribute.
689
	 * @see MethodMapper
690
	 */
691
	@SuppressWarnings("unused")
692
	private static String getNotes(RelationshipBase<?, ?, ?> relationship) {
693
		// TODO
694
		return null;
695
	}
696

    
697
	/**
698
	 * Returns the database key of an object in the given relationship.
699
	 * @param relationship {@link RelationshipBase RelationshipBase}.
700
	 * @param state {@link PesiExportState PesiExportState}.
701
	 * @param isFrom A boolean value indicating whether the database key of the parent or child in this relationship is searched. <code>true</code> means the child is searched. <code>false</code> means the parent is searched.
702
	 * @return The database key of an object in the given relationship.
703
	 */
704
	private static Integer getObjectFk(RelationshipBase<?, ?, ?> relationship, PesiExportState state, boolean isFrom) {
705
		TaxonBase<?> taxonBase = null;
706
		if (relationship.isInstanceOf(TaxonRelationship.class)) {
707
			TaxonRelationship tr = (TaxonRelationship)relationship;
708
			taxonBase = (isFrom) ? tr.getFromTaxon():  tr.getToTaxon();
709
		} else if (relationship.isInstanceOf(SynonymRelationship.class)) {
710
			SynonymRelationship sr = (SynonymRelationship)relationship;
711
			taxonBase = (isFrom) ? sr.getSynonym() : sr.getAcceptedTaxon();
712
		} else if (relationship.isInstanceOf(NameRelationship.class) ||  relationship.isInstanceOf(HybridRelationship.class)) {
713
			if (isFrom){
714
				return state.getDbId(state.getCurrentFromObject());
715
			}else{
716
				return state.getDbId(state.getCurrentToObject());
717
			}
718
		}
719
		if (taxonBase != null) {
720
			if (! isPesiTaxon(taxonBase)){
721
				logger.warn("Related taxonBase is not a PESI taxon. Taxon: " + taxonBase.getId() + "/" + taxonBase.getUuid() + "; TaxonRel: " +  relationship.getId() + "(" + relationship.getType().getTitleCache() + ")");
722
				return null;
723
			}else{
724
				return state.getDbId(taxonBase);	
725
			}
726
			
727
		}
728
		logger.warn("No taxon found in state for relationship: " + relationship.toString());
729
		return null;
730
	}
731

    
732
	/**
733
	 * Returns the <code>RankFk</code> attribute.
734
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
735
	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
736
	 * @return The <code>RankFk</code> attribute.
737
	 * @see MethodMapper
738
	 */
739
	private static Integer getRankFk(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
740
		Integer result = null;
741
		if (nomenclaturalCode != null) {
742
			if (taxonName != null && taxonName.getRank() == null) {
743
				logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
744
			}
745
			result = PesiTransformer.rank2RankId(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
746
			if (result == null) {
747
				logger.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode) + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
748
			}
749
		}
750
		return result;
751
	}
752

    
753
	/**
754
	 * Returns the <code>RankCache</code> attribute.
755
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
756
	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
757
	 * @return The <code>RankCache</code> attribute.
758
	 * @see MethodMapper
759
	 */
760
	private static String getRankCache(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
761
		String result = null;
762
		if (nomenclaturalCode != null) {
763
			result = PesiTransformer.rank2RankCache(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
764
		}
765
		return result;
766
	}
767

    
768
	/**
769
	 * Returns the CDM to PESI specific export mappings.
770
	 * @return The {@link PesiExportMapping PesiExportMapping}.
771
	 */
772
	PesiExportMapping getMapping() {
773
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
774
		
775
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk1", this.getClass(), "getTaxonFk1", standardMethodParameter, PesiExportState.class));
776
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk2", this.getClass(), "getTaxonFk2", standardMethodParameter, PesiExportState.class));
777
		mapping.addMapper(MethodMapper.NewInstance("RelTaxonQualifierFk", this));
778
		mapping.addMapper(MethodMapper.NewInstance("RelQualifierCache", this, RelationshipBase.class, PesiExportState.class));
779
		mapping.addMapper(MethodMapper.NewInstance("Notes", this));
780

    
781
		return mapping;
782
	}
783

    
784
}
(14-14/17)