Project

General

Profile

Download (26.7 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 Taxa..
111
//			success &= doPhase01(state, mapping);
112

    
113
			
114
			
115
			// 2nd Round: Add ParentTaxonFk, TreeIndex to each Taxon
116
			success &= doPhase02(state, mapping);
117

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

    
205
		
206
		return success;
207
	}
208

    
209
	private void makeList(TaxonNameBase<?, ?> name, List<IdentifiableEntity> list) {
210
		if (! hasPesiTaxon(name)){
211
			list.add(name);
212
		}else{
213
			for (TaxonBase taxon:  getPesiTaxa(name)){
214
				list.add(taxon);
215
			}
216
		}
217
	}
218

    
219
	/* (non-Javadoc)
220
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doInvoke(eu.etaxonomy.cdm.io.common.IoStateBase)
221
	 */
222
	protected void doInvoke_Old(PesiExportState state) {
223
		try {
224
			logger.info("*** Started Making " + pluralString + " ...");
225
	
226
			Connection connection = state.getConfig().getDestination().getConnection();
227
			String synonymsSql = "UPDATE Taxon SET KingdomFk = ?, RankFk = ?, RankCache = ? WHERE TaxonId = ?"; 
228
			synonymsStmt = connection.prepareStatement(synonymsSql);
229

    
230
			// Stores whether this invoke was successful or not.
231
			boolean success = true;
232

    
233
			// PESI: Clear the database table RelTaxon.
234
			doDelete(state);
235
	
236
			// Get specific mappings: (CDM) Relationship -> (PESI) RelTaxon
237
			mapping = getMapping();
238

    
239
			// Initialize the db mapper
240
			mapping.initialize(state);
241

    
242
			TransactionStatus txStatus = null;
243
			List<Classification> classificationList = null;
244
			
245
			// Specify starting ranks for tree traversing
246
			rankList.add(Rank.KINGDOM());
247
			rankList.add(Rank.GENUS());
248

    
249
			// Specify where to stop traversing (value) when starting at a specific Rank (key)
250
			rank2endRankMap.put(Rank.GENUS(), null); // Since NULL does not match an existing Rank, traverse all the way down to the leaves
251
			rank2endRankMap.put(Rank.KINGDOM(), Rank.GENUS()); // excludes rank genus
252
			
253
			// Retrieve list of classifications
254
			txStatus = startTransaction(true);
255
			logger.info("Started transaction. Fetching all classifications...");
256
			classificationList = getClassificationService().listClassifications(null, 0, null, null);
257
			commitTransaction(txStatus);
258
			logger.debug("Committed transaction.");
259

    
260
			logger.info("Fetched " + classificationList.size() + " classification(s).");
261

    
262
			for (Classification classification : classificationList) {
263
				for (Rank rank : rankList) {
264
					
265
					txStatus = startTransaction(true);
266
					logger.info("Started transaction to fetch all rootNodes specific to Rank " + rank.getLabel() + " ...");
267

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

    
271
					commitTransaction(txStatus);
272
					logger.debug("Committed transaction.");
273

    
274
					for (TaxonNode rootNode : rankSpecificRootNodes) {
275
						txStatus = startTransaction(false);
276
						Rank endRank = rank2endRankMap.get(rank);
277
						logger.debug("Started transaction to traverse childNodes of rootNode (" + rootNode.getUuid() + ") till " + (endRank == null ? "leaves are reached ..." : "Rank " + endRank.getLabel() + " ..."));
278
						
279
						TaxonNode newNode = getTaxonNodeService().load(rootNode.getUuid());
280

    
281
						if (isPesiTaxon(newNode.getTaxon())){
282
							
283
							TaxonNode parentNode = newNode.getParent();
284
	
285
							success &=traverseTree(newNode, parentNode, endRank, state);
286
	
287
							commitTransaction(txStatus);
288
							logger.debug("Committed transaction.");
289
						}else{
290
							logger.debug("Taxon is not in PESI");
291
						}
292

    
293
					}
294
				}
295
			}
296

    
297
			logger.warn("*** Finished Making " + pluralString + " ..." + getSuccessString(success));
298

    
299
			if (!success){
300
				state.setUnsuccessfull();
301
			}
302
			return;
303
		} catch (SQLException e) {
304
			e.printStackTrace();
305
			logger.error(e.getMessage());
306
			state.setUnsuccessfull();
307
			return;
308
		}
309
	}
310

    
311
	/**
312
	 * Traverses the classification recursively and stores determined values for every Taxon.
313
	 * @param childNode
314
	 * @param parentNode
315
	 * @param treeIndex
316
	 * @param fetchLevel
317
	 * @param state
318
	 */
319
	private boolean  traverseTree(TaxonNode childNode, TaxonNode parentNode, Rank fetchLevel, PesiExportState state) {
320
		boolean success = true;
321
		// Traverse all branches from this childNode until specified fetchLevel is reached.
322
		TaxonBase<?> childTaxon = childNode.getTaxon();
323
		if (childTaxon != null) {
324
			if (isPesiTaxon(childTaxon)){
325
				if (childTaxon.getName() != null) {
326
					Rank childTaxonNameRank = childTaxon.getName().getRank();
327
					if (childTaxonNameRank != null) {
328
						if (! childTaxonNameRank.equals(fetchLevel)) {
329
	
330
							success &= saveData(childNode, parentNode, state);
331
	
332
							for (TaxonNode newNode : childNode.getChildNodes()) {
333
								success &= traverseTree(newNode, childNode, fetchLevel, state);
334
							}
335
							
336
						} else {
337
	//						logger.error("Target Rank " + fetchLevel.getLabel() + " reached");
338
							return success;
339
						}
340
					} else {
341
						logger.warn("Rank is NULL. FetchLevel can not be checked: " + childTaxon.getUuid() + " (" + childTaxon.getTitleCache() + ")");
342
					}
343
				} else {
344
					logger.error("TaxonName is NULL for taxon: " + childTaxon.getUuid());
345
				}
346
			}else{
347
				logger.debug("Taxon is not a PESI taxon: " + childTaxon.getUuid());
348
			}
349

    
350
		} else {
351
			logger.error("Taxon is NULL for TaxonNode: " + childNode.getUuid());
352
		}
353
		return success;
354
	}
355

    
356
	/**
357
	 * Stores values in database for every recursive round.
358
	 * @param childNode
359
	 * @param parentNode
360
	 * @param treeIndex
361
	 * @param state
362
	 * @param currentTaxonFk
363
	 */
364
	private boolean saveData(TaxonNode childNode, TaxonNode parentNode, PesiExportState state) {
365
		boolean success = true;
366
		Taxon childNodeTaxon = childNode.getTaxon();
367
		if (childNodeTaxon != null) {
368
			// TaxonRelationships
369
			success &= saveTaxonRelationships(state, childNodeTaxon);
370
			// TaxonNameRelationships
371
			success &= saveNameRelationships(state, childNodeTaxon);
372
			// SynonymRelationships
373
			success &= saveSynonymAndSynNameRelationships(state, childNodeTaxon);
374
		}
375
		return success;
376
		
377
	}
378

    
379
	private boolean saveSynonymAndSynNameRelationships(PesiExportState state, Taxon childNodeTaxon) {
380
		boolean success = true;
381
		for (SynonymRelationship synRel : childNodeTaxon.getSynonymRelations()) { // synonyms of accepted taxon
382
			Synonym synonym = synRel.getSynonym();
383
			TaxonNameBase<?,?> synonymTaxonName = synonym.getName();
384
			if (! isPesiTaxon(synonym)){
385
				logger.warn("Synonym " + synonym.getId() + " of synonym relation " + synRel.getId() + " is not a PESI taxon. Can't export relationship");
386
				continue;
387
			}
388
			
389
			// Store synonym data in Taxon table
390
			invokeSynonyms(state, synonymTaxonName);
391

    
392
			
393
			
394
			Set<SynonymRelationship> synonymRelations = synonym.getSynonymRelations();
395
			state.setCurrentFromObject(synonym);
396
			for (SynonymRelationship synonymRelationship : synonymRelations) {  //needed? Maybe to make sure that there are no partial synonym relations missed ??
397
				try {
398
					if (neededValuesNotNull(synonymRelationship, state)) {
399
						doCount(count++, modCount, pluralString);
400
						success &= mapping.invoke(synonymRelationship);
401
						
402
					}
403
				} catch (SQLException e) {
404
					logger.error("SynonymRelationship (" + synonymRelationship.getUuid() + ") could not be stored : " + e.getMessage());
405
				}
406
			}
407

    
408
			// SynonymNameRelationship
409
			success &= saveNameRelationships(state, synonym);
410
		}
411
		return success;
412
	}
413

    
414
	private boolean saveNameRelationships(PesiExportState state, TaxonBase taxonBase) {
415
		boolean success = true;
416
		TaxonNameBase<?,?> childNodeTaxonName = taxonBase.getName();
417

    
418
		//from relations
419
		Set<NameRelationship> nameRelations = childNodeTaxonName.getRelationsFromThisName();
420
		state.setCurrentFromObject(taxonBase);
421
		boolean isFrom = true;
422
		success &= saveOneSideNameRelation(state, isFrom, nameRelations);
423
		
424
		//toRelations
425
		nameRelations = childNodeTaxonName.getRelationsToThisName();
426
		state.setCurrentToObject(taxonBase);
427
		isFrom = false;
428
		success &= saveOneSideNameRelation(state, isFrom, nameRelations);
429
		
430
		return success;
431
	}
432

    
433
	private boolean saveOneSideNameRelation(PesiExportState state, boolean isFrom, Set<NameRelationship> nameRelations) {
434
		boolean success = true;
435
		for (NameRelationship nameRelation : nameRelations) {
436
			try {
437
				TaxonNameBase<?,?> relatedName = isFrom ? nameRelation.getToName(): nameRelation.getFromName();
438
				if ( isPurePesiName(relatedName)){
439
					success &= checkAndInvokeNameRelation(state, nameRelation, relatedName, isFrom);
440
				}else{
441
					for (TaxonBase<?> relatedTaxon : getPesiTaxa(relatedName)){
442
						success &= checkAndInvokeNameRelation(state, nameRelation, relatedTaxon, isFrom);
443
					}
444
				}
445
			} catch (SQLException e) {
446
				logger.error("NameRelationship " + nameRelation.getUuid() + " for " + nameRelation.getFromName().getTitleCache() + " and " + nameRelation.getToName().getTitleCache() + " could not be created: " + e.getMessage());
447
				success = false;
448
			}
449
		}
450
		return success;
451
	}
452

    
453
	private boolean checkAndInvokeNameRelation(PesiExportState state, NameRelationship nameRelation, IdentifiableEntity<?> relatedObject, boolean isFrom) throws SQLException {
454
		boolean success = true;
455
		if (isFrom){
456
			state.setCurrentToObject(relatedObject);
457
		}else{
458
			state.setCurrentFromObject(relatedObject);
459
		}
460
		if (neededValuesNotNull(nameRelation, state)) {
461
			doCount(count++, modCount, pluralString);
462
			success &= mapping.invoke(nameRelation);
463
		}
464
		return success;
465
	}
466

    
467
	private boolean saveTaxonRelationships(PesiExportState state, Taxon childNodeTaxon) {
468
		boolean success = true;
469
		Taxon taxon = childNodeTaxon;
470
		Set<TaxonRelationship> taxonRelations = taxon.getRelationsToThisTaxon();
471
		for (TaxonRelationship taxonRelationship : taxonRelations) {
472
			try {
473
				if (neededValuesNotNull(taxonRelationship, state)) {
474
					doCount(count++, modCount, pluralString);
475
					success &= mapping.invoke(taxonRelationship);
476
				}
477
			} catch (SQLException e) {
478
				logger.error("TaxonRelationship could not be created for this TaxonRelation (" + taxonRelationship.getUuid() + "): " + e.getMessage());
479
			}
480
		}
481
		return success;
482
	}
483

    
484
	/**
485
	 * Determines synonym related data and saves them.
486
	 * @param state
487
	 * @param sr
488
	 */
489
	private static void invokeSynonyms(PesiExportState state, TaxonNameBase synonymTaxonName) {
490
		// Store KingdomFk and Rank information in Taxon table
491
		Integer kingdomFk = PesiTransformer.nomenClaturalCode2Kingdom(synonymTaxonName.getNomenclaturalCode());
492
		Integer synonymFk = state.getDbId(synonymTaxonName);
493

    
494
		saveSynonymData(synonymTaxonName, synonymTaxonName.getNomenclaturalCode(), kingdomFk, synonymFk);
495
	}
496

    
497
	/**
498
	 * Stores synonym data.
499
	 * @param taxonName
500
	 * @param nomenclaturalCode
501
	 * @param kingdomFk
502
	 * @param synonymParentTaxonFk
503
	 * @param currentTaxonFk
504
	 */
505
	private static boolean saveSynonymData(TaxonNameBase taxonName,
506
			NomenclaturalCode nomenclaturalCode, Integer kingdomFk,
507
			Integer currentSynonymFk) {
508
		try {
509
			if (kingdomFk != null) {
510
				synonymsStmt.setInt(1, kingdomFk);
511
			} else {
512
				synonymsStmt.setObject(1, null);
513
			}
514
			
515
			Integer rankFk = getRankFk(taxonName, nomenclaturalCode);
516
			if (rankFk != null) {
517
				synonymsStmt.setInt(2, rankFk);
518
			} else {
519
				synonymsStmt.setObject(2, null);
520
			}
521
			synonymsStmt.setString(3, getRankCache(taxonName, nomenclaturalCode));
522
			
523
			if (currentSynonymFk != null) {
524
				synonymsStmt.setInt(4, currentSynonymFk);
525
			} else {
526
				synonymsStmt.setObject(4, null);
527
			}
528
			synonymsStmt.executeUpdate();
529
			return true;
530
		} catch (SQLException e) {
531
			logger.error("SQLException during invoke for taxonName - " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + "): " + e.getMessage());
532
			e.printStackTrace();
533
			return false;
534
		}
535
	}
536

    
537
	/**
538
	 * Checks whether needed values for an entity are NULL.
539
	 * @return
540
	 */
541
	private boolean neededValuesNotNull(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
542
		boolean result = true;
543
		if (getTaxonFk1(relationship, state) == null) {
544
			logger.warn("TaxonFk1 is NULL, but is not allowed to be. Therefore no record was written to export database for this relationship: " + relationship.getUuid());
545
			result = false;
546
		}
547
		if (getTaxonFk2(relationship, state) == null) {
548
			logger.warn("TaxonFk2 is NULL, but is not allowed to be. Therefore no record was written to export database for this relationship: " + relationship.getUuid());
549
			result = false;
550
		}
551
		return result;
552
	}
553
	
554
	/**
555
	 * Deletes all entries of database tables related to <code>RelTaxon</code>.
556
	 * @param state The {@link PesiExportState PesiExportState}.
557
	 * @return Whether the delete operation was successful or not.
558
	 */
559
	protected boolean doDelete(PesiExportState state) {
560
		PesiExportConfigurator pesiConfig = (PesiExportConfigurator) state.getConfig();
561
		
562
		String sql;
563
		Source destination =  pesiConfig.getDestination();
564

    
565
		// Clear RelTaxon
566
		sql = "DELETE FROM " + dbTableName;
567
		destination.setQuery(sql);
568
		destination.update(sql);
569
		return true;
570
	}
571

    
572
	/* (non-Javadoc)
573
	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IoStateBase)
574
	 */
575
	@Override
576
	protected boolean isIgnore(PesiExportState state) {
577
		return ! state.getConfig().isDoRelTaxa();
578
	}
579

    
580
	/**
581
	 * Returns the <code>TaxonFk1</code> attribute. It corresponds to a CDM <code>TaxonRelationship</code>.
582
	 * @param relationship The {@link RelationshipBase Relationship}.
583
	 * @param state The {@link PesiExportState PesiExportState}.
584
	 * @return The <code>TaxonFk1</code> attribute.
585
	 * @see MethodMapper
586
	 */
587
	private static Integer getTaxonFk1(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
588
		return getObjectFk(relationship, state, true);
589
	}
590
	
591
	/**
592
	 * Returns the <code>TaxonFk2</code> attribute. It corresponds to a CDM <code>SynonymRelationship</code>.
593
	 * @param relationship The {@link RelationshipBase Relationship}.
594
	 * @param state The {@link PesiExportState PesiExportState}.
595
	 * @return The <code>TaxonFk2</code> attribute.
596
	 * @see MethodMapper
597
	 */
598
	private static Integer getTaxonFk2(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
599
		return getObjectFk(relationship, state, false);
600
	}
601
	
602
	/**
603
	 * Returns the <code>RelTaxonQualifierFk</code> attribute.
604
	 * @param relationship The {@link RelationshipBase Relationship}.
605
	 * @return The <code>RelTaxonQualifierFk</code> attribute.
606
	 * @see MethodMapper
607
	 */
608
	@SuppressWarnings("unused")
609
	private static Integer getRelTaxonQualifierFk(RelationshipBase<?, ?, ?> relationship) {
610
		return PesiTransformer.taxonRelation2RelTaxonQualifierFk(relationship);
611
	}
612
	
613
	/**
614
	 * Returns the <code>RelQualifierCache</code> attribute.
615
	 * @param relationship The {@link RelationshipBase Relationship}.
616
	 * @return The <code>RelQualifierCache</code> attribute.
617
	 * @see MethodMapper
618
	 */
619
	@SuppressWarnings("unused")
620
	private static String getRelQualifierCache(RelationshipBase<?, ?, ?> relationship, PesiExportState state) {
621
		String result = null;
622
		NomenclaturalCode code = null;
623
		if (relationship.isInstanceOf(TaxonRelationship.class)){
624
			code = CdmBase.deproxy(relationship, TaxonRelationship.class).getToTaxon().getName().getNomenclaturalCode();
625
		}else if (relationship.isInstanceOf(SynonymRelationship.class)){
626
			code = CdmBase.deproxy(relationship, SynonymRelationship.class).getAcceptedTaxon().getName().getNomenclaturalCode();
627
		}else if (relationship.isInstanceOf(NameRelationship.class)){
628
			code = CdmBase.deproxy(relationship,  NameRelationship.class).getFromName().getNomenclaturalCode();
629
		}
630
		if (code != null) {
631
			result = state.getConfig().getTransformer().getCacheByRelationshipType(relationship, code);
632
		} else {
633
			logger.error("NomenclaturalCode is NULL while creating the following relationship: " + relationship.getUuid());
634
		}
635
		return result;
636
	}
637
	
638
	/**
639
	 * Returns the <code>Notes</code> attribute.
640
	 * @param relationship The {@link RelationshipBase Relationship}.
641
	 * @return The <code>Notes</code> attribute.
642
	 * @see MethodMapper
643
	 */
644
	@SuppressWarnings("unused")
645
	private static String getNotes(RelationshipBase<?, ?, ?> relationship) {
646
		// TODO
647
		return null;
648
	}
649

    
650
	/**
651
	 * Returns the database key of an object in the given relationship.
652
	 * @param relationship {@link RelationshipBase RelationshipBase}.
653
	 * @param state {@link PesiExportState PesiExportState}.
654
	 * @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.
655
	 * @return The database key of an object in the given relationship.
656
	 */
657
	private static Integer getObjectFk(RelationshipBase<?, ?, ?> relationship, PesiExportState state, boolean isFrom) {
658
		TaxonBase<?> taxonBase = null;
659
		if (relationship.isInstanceOf(TaxonRelationship.class)) {
660
			TaxonRelationship tr = (TaxonRelationship)relationship;
661
			taxonBase = (isFrom) ? tr.getFromTaxon():  tr.getToTaxon();
662
		} else if (relationship.isInstanceOf(SynonymRelationship.class)) {
663
			SynonymRelationship sr = (SynonymRelationship)relationship;
664
			taxonBase = (isFrom) ? sr.getSynonym() : sr.getAcceptedTaxon();
665
		} else if (relationship.isInstanceOf(NameRelationship.class) ||  relationship.isInstanceOf(HybridRelationship.class)) {
666
			if (isFrom){
667
				return state.getDbId(state.getCurrentFromObject());
668
			}else{
669
				return state.getDbId(state.getCurrentToObject());
670
			}
671
		}
672
		if (taxonBase != null) {
673
			if (! isPesiTaxon(taxonBase)){
674
				logger.warn("Related taxonBase is not a PESI taxon. Taxon: " + taxonBase.getId() + "/" + taxonBase.getUuid() + "; TaxonRel: " +  relationship.getId() + "(" + relationship.getType().getTitleCache() + ")");
675
				return null;
676
			}else{
677
				return state.getDbId(taxonBase);	
678
			}
679
			
680
		}
681
		logger.warn("No taxon found in state for relationship: " + relationship.toString());
682
		return null;
683
	}
684

    
685
	/**
686
	 * Returns the <code>RankFk</code> attribute.
687
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
688
	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
689
	 * @return The <code>RankFk</code> attribute.
690
	 * @see MethodMapper
691
	 */
692
	private static Integer getRankFk(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
693
		Integer result = null;
694
		if (nomenclaturalCode != null) {
695
			if (taxonName != null && taxonName.getRank() == null) {
696
				logger.warn("Rank is null: " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
697
			}
698
			result = PesiTransformer.rank2RankId(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
699
			if (result == null) {
700
				logger.warn("Rank could not be determined for PESI-Kingdom-Id " + PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode) + " and TaxonName " + taxonName.getUuid() + " (" + taxonName.getTitleCache() + ")");
701
			}
702
		}
703
		return result;
704
	}
705

    
706
	/**
707
	 * Returns the <code>RankCache</code> attribute.
708
	 * @param taxonName The {@link TaxonNameBase TaxonName}.
709
	 * @param nomenclaturalCode The {@link NomenclaturalCode NomenclaturalCode}.
710
	 * @return The <code>RankCache</code> attribute.
711
	 * @see MethodMapper
712
	 */
713
	private static String getRankCache(TaxonNameBase taxonName, NomenclaturalCode nomenclaturalCode) {
714
		String result = null;
715
		if (nomenclaturalCode != null) {
716
			result = PesiTransformer.rank2RankCache(taxonName.getRank(), PesiTransformer.nomenClaturalCode2Kingdom(nomenclaturalCode));
717
		}
718
		return result;
719
	}
720

    
721
	/**
722
	 * Returns the CDM to PESI specific export mappings.
723
	 * @return The {@link PesiExportMapping PesiExportMapping}.
724
	 */
725
	private PesiExportMapping getMapping() {
726
		PesiExportMapping mapping = new PesiExportMapping(dbTableName);
727
		
728
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk1", this.getClass(), "getTaxonFk1", standardMethodParameter, PesiExportState.class));
729
		mapping.addMapper(MethodMapper.NewInstance("TaxonFk2", this.getClass(), "getTaxonFk2", standardMethodParameter, PesiExportState.class));
730
		mapping.addMapper(MethodMapper.NewInstance("RelTaxonQualifierFk", this));
731
		mapping.addMapper(MethodMapper.NewInstance("RelQualifierCache", this, RelationshipBase.class, PesiExportState.class));
732
		mapping.addMapper(MethodMapper.NewInstance("Notes", this));
733

    
734
		return mapping;
735
	}
736

    
737
}
(14-14/17)