Project

General

Profile

Download (27.5 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
		list = null;
156
		
157
		return success;
158
	}
159
	
160
	private boolean doPhase02(PesiExportState state, PesiExportMapping mapping2) throws SQLException {
161
		logger.info("PHASE 2: Name Relationships ...");
162
		boolean success = true;
163
		
164
		int limit = state.getConfig().getLimitSave();
165
		// Start transaction
166
		TransactionStatus txStatus = startTransaction(true);
167
		logger.info("Started new transaction. Fetching some " + pluralString + " (max: " + limit + ") ...");
168
		
169
		List<RelationshipBase> list;
170
		
171
		//name relations
172
		int partitionCount = 0;
173
		while ((list = getNextNameRelationshipPartition(null, limit, partitionCount++, null)) != null   ) {
174
			for (RelationshipBase rel : list){
175
				try {
176
					TaxonNameBase<?,?> name1;
177
					TaxonNameBase<?,?> name2;
178
					if (rel.isInstanceOf(HybridRelationship.class)){
179
						HybridRelationship hybridRel = CdmBase.deproxy(rel, HybridRelationship.class);
180
						name1 = hybridRel.getParentName();
181
						name2 = hybridRel.getHybridName();
182
					}else if (rel.isInstanceOf(NameRelationship.class)){
183
						NameRelationship nameRel = CdmBase.deproxy(rel, NameRelationship.class);
184
						name1 = nameRel.getFromName();
185
						name2 = nameRel.getToName();
186
					}else{
187
						logger.warn ("Only hybrid- and name-relationships alowed here");
188
						continue;
189
					}
190
					List<IdentifiableEntity> fromList = new ArrayList<IdentifiableEntity>();
191
					List<IdentifiableEntity> toList = new ArrayList<IdentifiableEntity>();
192
					makeList(name1, fromList);
193
					makeList(name2, toList);
194
					
195
					for (IdentifiableEntity fromEntity : fromList){
196
						for (IdentifiableEntity toEntity : toList){
197
							//TODO set entities to state
198
							state.setCurrentFromObject(fromEntity);
199
							state.setCurrentToObject(toEntity);
200
							mapping.invoke(rel);
201
						}
202
					}
203
					fromList = null;
204
					toList = null;
205
					name1 = null;
206
					name2 = null;
207
					rel = null;
208
					
209
					
210
				} catch (Exception e) {
211
					logger.error(e.getMessage() + ". Relationship: " +  rel.getUuid());
212
					e.printStackTrace();
213
				}
214
			}
215
		}
216
		list = null;
217
		logger.info("End PHASE 2: Name Relationships ...");
218
		state.setCurrentFromObject(null);
219
		state.setCurrentToObject(null);	
220
		return success;
221
	}
222

    
223
	private void makeList(TaxonNameBase<?, ?> name, List<IdentifiableEntity> list) {
224
		if (! hasPesiTaxon(name)){
225
			list.add(name);
226
		}else{
227
			for (TaxonBase taxon:  getPesiTaxa(name)){
228
				list.add(taxon);
229
			}
230
		}
231
	}
232

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

    
244
			// Stores whether this invoke was successful or not.
245
			boolean success = true;
246

    
247
			// PESI: Clear the database table RelTaxon.
248
			doDelete(state);
249
	
250
			// Get specific mappings: (CDM) Relationship -> (PESI) RelTaxon
251
			mapping = getMapping();
252

    
253
			// Initialize the db mapper
254
			mapping.initialize(state);
255

    
256
			TransactionStatus txStatus = null;
257
			List<Classification> classificationList = null;
258
			
259
			// Specify starting ranks for tree traversing
260
			rankList.add(Rank.KINGDOM());
261
			rankList.add(Rank.GENUS());
262

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

    
274
			logger.info("Fetched " + classificationList.size() + " classification(s).");
275

    
276
			for (Classification classification : classificationList) {
277
				for (Rank rank : rankList) {
278
					
279
					txStatus = startTransaction(true);
280
					logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
281

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

    
285
					commitTransaction(txStatus);
286
					logger.debug("Committed transaction.");
287

    
288
					for (TaxonNode rootNode : rankSpecificRootNodes) {
289
						txStatus = startTransaction(false);
290
						Rank endRank = rank2endRankMap.get(rank);
291
						logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till " + (endRank == null ? "leaves are reached ..." : "Rank " + endRank.getLabel() + " ..."));
292
						
293
						TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
294

    
295
						if (isPesiTaxon(newNode.getTaxon())){
296
							
297
							TaxonNode parentNode = newNode.getParent();
298
	
299
							success &=traverseTree(newNode, parentNode, endRank, state);
300
	
301
							commitTransaction(txStatus);
302
							logger.debug("Committed transaction.");
303
						}else{
304
							logger.debug("Taxon is not in PESI");
305
						}
306

    
307
					}
308
				}
309
			}
310

    
311
			logger.warn("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
312

    
313
			if (!success){
314
				state.setUnsuccessfull();
315
			}
316
			return;
317
		} catch (SQLException e) {
318
			e.printStackTrace();
319
			logger.error(e.getMessage());
320
			state.setUnsuccessfull();
321
			return;
322
		}
323
	}
324

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

    
364
		} else {
365
			logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());
366
		}
367
		return success;
368
	}
369

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

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

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

    
422
			// SynonymNameRelationship
423
			success &= saveNameRelationships(state, synonym);
424
		}
425
		state.setCurrentFromObject(null);
426
		return success;
427
	}
428

    
429
	private boolean saveNameRelationships(PesiExportState state, TaxonBase taxonBase) {
430
		boolean success = true;
431
		TaxonNameBase<?,?> childNodeTaxonName = taxonBase.getName();
432

    
433
		//from relations
434
		Set<NameRelationship> nameRelations = childNodeTaxonName.getRelationsFromThisName();
435
		state.setCurrentFromObject(taxonBase);
436
		boolean isFrom = true;
437
		success &= saveOneSideNameRelation(state, isFrom, nameRelations);
438
		
439
		//toRelations
440
		nameRelations = childNodeTaxonName.getRelationsToThisName();
441
		state.setCurrentToObject(taxonBase);
442
		isFrom = false;
443
		success &= saveOneSideNameRelation(state, isFrom, nameRelations);
444
		state.setCurrentToObject(null);
445
		return success;
446
	}
447

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

    
468
	private boolean checkAndInvokeNameRelation(PesiExportState state, NameRelationship nameRelation, IdentifiableEntity<?> relatedObject, boolean isFrom) throws SQLException {
469
		boolean success = true;
470
		if (isFrom){
471
			state.setCurrentToObject(relatedObject);
472
		}else{
473
			state.setCurrentFromObject(relatedObject);
474
		}
475
		if (neededValuesNotNull(nameRelation, state)) {
476
			doCount(count++, modCount, pluralString);
477
			success &= mapping.invoke(nameRelation);
478
		}
479
		state.setCurrentFromObject(null);
480
		state.setCurrentToObject(null);
481
		return success;
482
	}
483

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

    
501
	/**
502
	 * Determines synonym related data and saves them.
503
	 * @param state
504
	 * @param sr
505
	 */
506
	private static void invokeSynonyms(PesiExportState state, TaxonNameBase synonymTaxonName) {
507
		// Store KingdomFk and Rank information in Taxon table
508
		Integer kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(synonymTaxonName.getNomenclaturalCode());
509
		Integer synonymFk = state.getDbId(synonymTaxonName);
510

    
511
		saveSynonymData(synonymTaxonName, synonymTaxonName.getNomenclaturalCode(), kingdomFk, synonymFk);
512
	}
513

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

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

    
582
		// Clear RelTaxon
583
		sql = "DELETE FROM " + dbTableName;
584
		destination.setQuery(sql);
585
		destination.update(sql);
586
		return true;
587
	}
588

    
589
	/* (non-Javadoc)
590
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
591
	 */
592
	@Override
593
	protected boolean isIgnore(PesiExportState state) {
594
		return ! state.getConfig().isDoRelTaxa();
595
	}
596

    
597
	/**
598
	 * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
599
	 * @param relationship The {@link RelationshipBase Relationship}.
600
	 * @param state The {@link PesiExportState PesiExportState}.
601
	 * @return The <code>TaxonFk1</code> attribute.
602
	 * @see MethodMapper
603
	 */
604
	private static Integer getTaxonFk1(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
605
		return getObjectFk(relationship, state, true);
606
	}
607
	
608
	/**
609
	 * Returns the <code>TaxonFk2</code> attribute. It corresponds to a CDM <code>SynonymRelationship</code>.
610
	 * @param relationship The {@link RelationshipBase Relationship}.
611
	 * @param state The {@link PesiExportState PesiExportState}.
612
	 * @return The <code>TaxonFk2</code> attribute.
613
	 * @see MethodMapper
614
	 */
615
	private static Integer getTaxonFk2(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
616
		return getObjectFk(relationship, state, false);
617
	}
618
	
619
	/**
620
	 * Returns the <code>RelTaxonQualifierFk</code> attribute.
621
	 * @param relationship The {@link RelationshipBase Relationship}.
622
	 * @return The <code>RelTaxonQualifierFk</code> attribute.
623
	 * @see MethodMapper
624
	 */
625
	@SuppressWarnings("unused")
626
	private static Integer getRelTaxonQualifierFk(RelationshipBase<?, ?, ?> relationship) {
627
		return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);
628
	}
629
	
630
	/**
631
	 * Returns the <code>RelQualifierCache</code> attribute.
632
	 * @param relationship The {@link RelationshipBase Relationship}.
633
	 * @return The <code>RelQualifierCache</code> attribute.
634
	 * @see MethodMapper
635
	 */
636
	@SuppressWarnings("unused")
637
	private static String getRelQualifierCache(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
638
		String result = null;
639
		NomenclaturalCode code = null;
640
		if (relationship.isInstanceOf(TaxonRelationship.class)){
641
			code = CdmBase.deproxy(relationship, TaxonRelationship.class).getToTaxon().getName().getNomenclaturalCode();
642
		}else if (relationship.isInstanceOf(SynonymRelationship.class)){
643
			code = CdmBase.deproxy(relationship, SynonymRelationship.class).getAcceptedTaxon().getName().getNomenclaturalCode();
644
		}else if (relationship.isInstanceOf(NameRelationship.class)){
645
			code = CdmBase.deproxy(relationship,  NameRelationship.class).getFromName().getNomenclaturalCode();
646
		}else if (relationship.isInstanceOf(HybridRelationship.class)){
647
			code = CdmBase.deproxy(relationship,  HybridRelationship.class).getParentName().getNomenclaturalCode();
648
		}
649
		if (code != null) {
650
			result = state.getConfig().getTransformer().getCacheByRelationshipType(relationship, code);
651
		} else {
652
			logger.error("NomenclaturalCode is NULL while creating the following relationship: " + relationship.getUuid());
653
		}
654
		return result;
655
	}
656
	
657
	/**
658
	 * Returns the <code>Notes</code> attribute.
659
	 * @param relationship The {@link RelationshipBase Relationship}.
660
	 * @return The <code>Notes</code> attribute.
661
	 * @see MethodMapper
662
	 */
663
	@SuppressWarnings("unused")
664
	private static String getNotes(RelationshipBase<?, ?, ?> relationship) {
665
		// TODO
666
		return null;
667
	}
668

    
669
	/**
670
	 * Returns the database key of an object in the given relationship.
671
	 * @param relationship {@link RelationshipBase RelationshipBase}.
672
	 * @param state {@link PesiExportState PesiExportState}.
673
	 * @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.
674
	 * @return The database key of an object in the given relationship.
675
	 */
676
	private static Integer getObjectFk(RelationshipBase<?, ?, ?> relationship, PesiExportState state, boolean isFrom) {
677
		TaxonBase<?> taxonBase = null;
678
		if (relationship.isInstanceOf(TaxonRelationship.class)) {
679
			TaxonRelationship tr = (TaxonRelationship)relationship;
680
			taxonBase = (isFrom) ? tr.getFromTaxon():  tr.getToTaxon();
681
		} else if (relationship.isInstanceOf(SynonymRelationship.class)) {
682
			SynonymRelationship sr = (SynonymRelationship)relationship;
683
			taxonBase = (isFrom) ? sr.getSynonym() : sr.getAcceptedTaxon();
684
		} else if (relationship.isInstanceOf(NameRelationship.class) ||  relationship.isInstanceOf(HybridRelationship.class)) {
685
			if (isFrom){
686
				return state.getDbId(state.getCurrentFromObject());
687
			}else{
688
				return state.getDbId(state.getCurrentToObject());
689
			}
690
		}
691
		if (taxonBase != null) {
692
			if (! isPesiTaxon(taxonBase)){
693
				logger.warn("Related taxonBase is not a PESI taxon. Taxon: " + taxonBase.getId() + "/" + taxonBase.getUuid() + "; TaxonRel: " +  relationship.getId() + "(" + relationship.getType().getTitleCache() + ")");
694
				return null;
695
			}else{
696
				return state.getDbId(taxonBase);	
697
			}
698
			
699
		}
700
		logger.warn("No taxon found in state for relationship: " + relationship.toString());
701
		return null;
702
	}
703

    
704
	/**
705
	 * Returns the <code>RankFk</code> attribute.
706
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
707
	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
708
	 * @return The <code>RankFk</code> attribute.
709
	 * @see MethodMapper
710
	 */
711
	private static Integer getRankFk(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
712
		Integer result = null;
713
		if (nomenclaturalCode != null) {
714
			if (taxonName != null && taxonName.getRank() == null) {
715
				logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
716
			}
717
			result = PesiTransformer.rank2RankId(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
718
			if (result == null) {
719
				logger.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode) + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
720
			}
721
		}
722
		return result;
723
	}
724

    
725
	/**
726
	 * Returns the <code>RankCache</code> attribute.
727
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
728
	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
729
	 * @return The <code>RankCache</code> attribute.
730
	 * @see MethodMapper
731
	 */
732
	private static String getRankCache(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
733
		String result = null;
734
		if (nomenclaturalCode != null) {
735
			result = PesiTransformer.rank2RankCache(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
736
		}
737
		return result;
738
	}
739

    
740
	/**
741
	 * Returns the CDM to PESI specific export mappings.
742
	 * @return The {@link PesiExportMapping PesiExportMapping}.
743
	 */
744
	PesiExportMapping getMapping() {
745
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
746
		
747
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk1", this.getClass(), "getTaxonFk1", standardMethodParameter, PesiExportState.class));
748
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk2", this.getClass(), "getTaxonFk2", standardMethodParameter, PesiExportState.class));
749
		mapping.addMapper(MethodMapper.NewInstance("RelTaxonQualifierFk", this));
750
		mapping.addMapper(MethodMapper.NewInstance("RelQualifierCache", this, RelationshipBase.class, PesiExportState.class));
751
		mapping.addMapper(MethodMapper.NewInstance("Notes", this));
752

    
753
		return mapping;
754
	}
755

    
756
}
(14-14/17)