View Javadoc

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.faunaEuropaea;
11  
12  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.A_AUCT;
13  
14  import java.sql.ResultSet;
15  import java.sql.SQLException;
16  import java.util.HashMap;
17  import java.util.HashSet;
18  import java.util.List;
19  import java.util.Map;
20  import java.util.Set;
21  import java.util.UUID;
22  
23  import org.apache.log4j.Logger;
24  import org.springframework.stereotype.Component;
25  import org.springframework.transaction.TransactionStatus;
26  
27  import eu.etaxonomy.cdm.io.common.ICdmIO;
28  import eu.etaxonomy.cdm.io.common.MapWrapper;
29  import eu.etaxonomy.cdm.io.common.Source;
30  import eu.etaxonomy.cdm.io.profiler.ProfilerController;
31  import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
32  import eu.etaxonomy.cdm.model.common.CdmBase;
33  import eu.etaxonomy.cdm.model.reference.ReferenceBase;
34  import eu.etaxonomy.cdm.model.taxon.Synonym;
35  import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
36  import eu.etaxonomy.cdm.model.taxon.Taxon;
37  import eu.etaxonomy.cdm.model.taxon.TaxonBase;
38  import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
39  
40  
41  
42  /**
43   * @author a.babadshanjan
44   * @created 12.05.2009
45   * @version 1.0
46   */
47  @Component
48  public class FaunaEuropaeaRelTaxonIncludeImport extends FaunaEuropaeaImportBase  {
49  	
50  	public static final String OS_NAMESPACE_TAXON = "Taxon";
51  	private static final Logger logger = Logger.getLogger(FaunaEuropaeaRelTaxonIncludeImport.class);
52  	private static final String acceptedTaxonUUID = "A9C24E42-69F5-4681-9399-041E652CF338"; // any accepted taxon uuid, taken from original fauna europaea database
53  	
54  	private ReferenceBase<?> sourceRef;
55  	private static String ALL_SYNONYM_FROM_CLAUSE = " FROM Taxon INNER JOIN Taxon AS Parent " +
56  	" ON Taxon.TAX_TAX_IDPARENT = Parent.TAX_ID " +
57  	" WHERE (Taxon.TAX_VALID = 0) " +
58  	" AND (Taxon.TAX_AUT_ID <> " + A_AUCT + " OR Taxon.TAX_AUT_ID IS NULL)";
59  
60  	/* (non-Javadoc)
61  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IImportConfigurator)
62  	 */
63  	@Override
64  	protected boolean doCheck(FaunaEuropaeaImportState state) {
65  		boolean result = true;
66  		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
67  		logger.warn("Checking for Taxa not yet fully implemented");
68  		result &= checkTaxonStatus(fauEuConfig);
69  		
70  		return result;
71  	}
72  	
73  	/* (non-Javadoc)
74  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
75  	 */
76  	protected boolean isIgnore(FaunaEuropaeaImportState state) {
77  		return ! (state.getConfig().isDoTaxonomicallyIncluded() || 
78  		state.getConfig().isDoMisappliedNames() || state.getConfig().isDoHeterotypicSynonyms());
79  	}
80  
81  	private boolean checkTaxonStatus(FaunaEuropaeaImportConfigurator fauEuConfig) {
82  		boolean result = true;
83  //		try {
84  			Source source = fauEuConfig.getSource();
85  			String sqlStr = "";
86  			ResultSet rs = source.getResultSet(sqlStr);
87  			return result;
88  //		} catch (SQLException e) {
89  //			e.printStackTrace();
90  //			return false;
91  //		}
92  	}
93  	
94  	protected boolean doInvoke(FaunaEuropaeaImportState state) {				
95  		
96  		boolean success = true;
97  
98  		Map<String, MapWrapper<? extends CdmBase>> stores = state.getStores();
99  
100 		MapWrapper<TeamOrPersonBase> authorStore = (MapWrapper<TeamOrPersonBase>)stores.get(ICdmIO.TEAM_STORE);
101 		authorStore.makeEmpty();
102 
103 		if(logger.isInfoEnabled()) { logger.info("Start making relationships..."); }
104 
105 		TransactionStatus txStatus = startTransaction();
106 		
107 		// the uuid of an accepted taxon is needed here. any accepted taxon will do.
108 		TaxonBase taxon = getTaxonService().find(UUID.fromString(acceptedTaxonUUID));
109 		sourceRef = taxon.getSec();
110 
111 		TaxonomicTree tree = getTaxonomicTreeFor(state, sourceRef);
112 		commitTransaction(txStatus);
113 		
114 		//ProfilerController.memorySnapshot();
115 		if (state.getConfig().isDoTaxonomicallyIncluded()) {
116 			success = processParentsChildren(state);
117 		}
118 		//ProfilerController.memorySnapshot();
119 		if (state.getConfig().isDoMisappliedNames()) {
120 			success = processMisappliedNames(state);
121 		}
122 		//ProfilerController.memorySnapshot();
123 		if (state.getConfig().isDoHeterotypicSynonyms()) {
124 			if(logger.isInfoEnabled()) { 
125 				logger.info("Start making heterotypic synonym relationships..."); 
126 			}
127 			success = processHeterotypicSynonyms(state, ALL_SYNONYM_FROM_CLAUSE);
128 		}
129 		//ProfilerController.memorySnapshot();
130 
131 		logger.info("End making taxa...");
132 
133 		return success;
134 	}
135 
136 	/** Retrieve child-parent uuid map from CDM DB */
137 	private boolean processParentsChildren(FaunaEuropaeaImportState state) {
138 
139 		int limit = state.getConfig().getLimitSave();
140 
141 		TransactionStatus txStatus = null;
142 
143 		Map<UUID, UUID> childParentMap = null;
144 		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
145 		Source source = fauEuConfig.getSource();
146 		int i = 0;
147 		boolean success = true;
148 
149 		String selectCount = 
150 			" SELECT count(*) ";
151 
152 		String selectColumns = " SELECT Taxon.UUID AS ChildUuid, Parent.UUID AS ParentUuid ";
153 		
154 		String fromClause = " FROM Taxon INNER JOIN Taxon AS Parent " +
155 		" ON Taxon.TAX_TAX_IDPARENT = Parent.TAX_ID " +
156 		" WHERE (Taxon.TAX_VALID <> 0) AND (Taxon.TAX_AUT_ID <> " + A_AUCT + " OR Taxon.TAX_AUT_ID IS NULL )";
157 		
158 		String orderClause = " ORDER BY Taxon.TAX_RNK_ID ASC";
159 
160 		String countQuery = 
161 			selectCount + fromClause;
162 
163 		String selectQuery = 
164 			selectColumns + fromClause + orderClause;
165 			
166 		if(logger.isInfoEnabled()) { logger.info("Start making taxonomically included relationships..."); }
167 		
168 		try {
169 
170 			ResultSet rs = source.getResultSet(countQuery);
171 			rs.next();
172 			int count = rs.getInt(1);
173 			
174 			rs = source.getResultSet(selectQuery);
175 
176 	        if (logger.isInfoEnabled()) {
177 				logger.info("Number of rows: " + count);
178 				logger.info("Count Query: " + countQuery);
179 				logger.info("Select Query: " + selectQuery);
180 			}
181 
182 	        while (rs.next()) {
183 				
184 				if ((i++ % limit) == 0) {
185 					
186 					txStatus = startTransaction();
187 					childParentMap = new HashMap<UUID, UUID>(limit);
188 					
189 					if(logger.isInfoEnabled()) {
190 						logger.info("Taxonomically included retrieved: " + (i-1)); 
191 					}
192 				}
193 
194 				String childUuidStr = rs.getString("ChildUuid");
195 				String parentUuidStr = rs.getString("ParentUuid");
196 				UUID childUuid = UUID.fromString(childUuidStr);
197 				UUID parentUuid = UUID.fromString(parentUuidStr);
198 				
199 				if (!childParentMap.containsKey(childUuid)) {
200 
201 						childParentMap.put(childUuid, parentUuid);
202 
203 				} else {
204 					if(logger.isDebugEnabled()) {
205 						logger.debug("Duplicated child UUID (" + childUuid + ")");
206 					}
207 				}
208 				if (((i % limit) == 0 && i != 1 ) || i == count) { 
209 
210 					success = createParentChildRelationships(state, childParentMap);
211 
212 					childParentMap = null;
213 					commitTransaction(txStatus);
214 
215 					if(logger.isInfoEnabled()) {
216 						logger.info("i = " + i + " - Transaction committed"); 
217 					}
218 				}
219 			}
220 
221 		} catch (SQLException e) {
222 			logger.error("SQLException:" +  e);
223 			success = false;
224 		}
225 		return success;		
226 	}
227 	
228 
229 	/** Retrieve misapplied name / accepted taxon uuid map from CDM DB */
230 	private boolean processMisappliedNames(FaunaEuropaeaImportState state) {
231 
232 		int limit = state.getConfig().getLimitSave();
233 
234 		TransactionStatus txStatus = null;
235 
236 		Map<UUID, UUID> childParentMap = null;
237 		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
238 		Source source = fauEuConfig.getSource();
239 		int i = 0;
240 		boolean success = true;
241 
242 		String selectCount = 
243 			" SELECT count(*) ";
244 
245 		String selectColumns = " SELECT Taxon.UUID AS MisappliedUuid, Parent.UUID AS AcceptedUuid ";
246 		
247 		String fromClause = " FROM Taxon INNER JOIN Taxon AS Parent " +
248 		" ON Taxon.TAX_TAX_IDPARENT = Parent.TAX_ID " +
249 		" WHERE (Taxon.TAX_VALID = 0) AND (Taxon.TAX_AUT_ID = " + A_AUCT + ")";
250 		
251 		String orderClause = " ORDER BY dbo.Taxon.TAX_RNK_ID ASC ";
252 
253 		String countQuery = 
254 			selectCount + fromClause;
255 
256 		String selectQuery = 
257 			selectColumns + fromClause + orderClause;
258 			
259 		if(logger.isInfoEnabled()) { logger.info("Start making misapplied name relationships..."); }
260 
261 		try {
262 
263 			ResultSet rs = source.getResultSet(countQuery);
264 			rs.next();
265 			int count = rs.getInt(1);
266 			
267 			rs = source.getResultSet(selectQuery);
268 
269 	        if (logger.isInfoEnabled()) {
270 				logger.info("Number of rows: " + count);
271 				logger.info("Count Query: " + countQuery);
272 				logger.info("Select Query: " + selectQuery);
273 			}
274 
275 			while (rs.next()) {
276 				
277 				if ((i++ % limit) == 0) {
278 					
279 					txStatus = startTransaction();
280 					childParentMap = new HashMap<UUID, UUID>(limit);
281 					
282 					if(logger.isInfoEnabled()) {
283 						logger.info("Misapplied names retrieved: " + (i-1) ); 
284 					}
285 				}
286 
287 				String childUuidStr = rs.getString("MisappliedUuid");
288 				String parentUuidStr = rs.getString("AcceptedUuid");
289 				UUID childUuid = UUID.fromString(childUuidStr);
290 				UUID parentUuid = UUID.fromString(parentUuidStr);
291 				
292 				if (!childParentMap.containsKey(childUuid)) {
293 
294 						childParentMap.put(childUuid, parentUuid);
295 
296 				} else {
297 					if(logger.isDebugEnabled()) {
298 						logger.debug("Duplicated child UUID (" + childUuid + ")");
299 					}
300 				}
301 
302 				if (((i % limit) == 0 && i != 1 ) || i == count) { 
303 
304 					success = createMisappliedNameRelationships(state, childParentMap);
305 
306 					childParentMap = null;
307 					commitTransaction(txStatus);
308 
309 					if(logger.isInfoEnabled()) {
310 						logger.info("i = " + i + " - Transaction committed"); 
311 					}
312 				}
313 			}
314 
315 		} catch (SQLException e) {
316 			logger.error("SQLException:" +  e);
317 			success = false;
318 		}
319 		return success;		
320 	}
321 
322 
323 
324 	/** Retrieve synonyms from FauEuDB DB */
325 	private boolean processHeterotypicSynonyms(FaunaEuropaeaImportState state, String fromClause) {
326 
327 		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
328 		Source source = fauEuConfig.getSource();
329 		boolean success = true;
330 
331 		String selectCount = 
332 			" SELECT count(*) ";
333 
334 		String selectColumns = " SELECT Taxon.UUID AS SynonymUuid, Parent.UUID AS AcceptedUuid ";
335 		
336 		String orderClause = " ORDER BY dbo.Taxon.TAX_RNK_ID ASC ";
337 
338 		String countQuery = 
339 			selectCount + fromClause;
340 
341 		String selectQuery = 
342 			selectColumns + fromClause + orderClause;
343 		logger.debug(selectQuery);
344 			
345 		try {
346 
347 			ResultSet rs = source.getResultSet(countQuery);
348 			rs.next();
349 			int count = rs.getInt(1);
350 			
351 			rs = source.getResultSet(selectQuery);
352 
353 	        if (logger.isInfoEnabled()) {
354 				logger.info("Number of rows: " + count);
355 				logger.info("Count Query: " + countQuery);
356 				logger.info("Select Query: " + selectQuery);
357 			}
358 	        
359 	        success = storeSynonymRelationships(rs, count, state);
360 
361 		} catch (SQLException e) {
362 			logger.error("SQLException:" +  e);
363 			success = false;
364 		}
365 		return success;		
366 	}
367 	
368 	
369 
370 	
371 	private boolean storeSynonymRelationships(ResultSet rs, int count, FaunaEuropaeaImportState state) 
372 	throws SQLException {
373 
374 		TransactionStatus txStatus = null;
375 		Map<UUID, UUID> synonymAcceptedMap = null;
376 		int i = 0;
377 		boolean success = true;
378 		int limit = state.getConfig().getLimitSave();
379 
380 		while (rs.next()) {
381 
382 			if ((i++ % limit) == 0) {
383 
384 				txStatus = startTransaction();
385 				synonymAcceptedMap = new HashMap<UUID, UUID>(limit);
386 
387 				if(logger.isInfoEnabled()) {
388 					logger.info("Synonyms retrieved: " + (i-1)); 
389 				}
390 			}
391 
392 			String synonymUuidStr = rs.getString("SynonymUuid");
393 			String acceptedUuidStr = rs.getString("AcceptedUuid");
394 			UUID synonymUuid = UUID.fromString(synonymUuidStr);
395 			UUID acceptedUuid = UUID.fromString(acceptedUuidStr);
396 
397 			if (!synonymAcceptedMap.containsKey(synonymUuid)) {
398 
399 				synonymAcceptedMap.put(synonymUuid, acceptedUuid);
400 
401 			} else {
402 				if(logger.isDebugEnabled()) {
403 					logger.debug("Duplicated synonym UUID (" + synonymUuid + ")");
404 				}
405 			}
406 
407 			if (((i % limit) == 0 && i != 1 ) || i == count) { 
408 
409 				success = createHeterotypicSynonyms(state, synonymAcceptedMap);
410 
411 				synonymAcceptedMap = null;
412 				commitTransaction(txStatus);
413 
414 				if(logger.isInfoEnabled()) {
415 					logger.info("i = " + i + " - Transaction committed"); 
416 				}
417 			}
418 		}
419 		return success;
420 	}
421 	
422 	
423 	
424 	
425 
426 	/* Creates parent-child relationships.
427 	 * Parent-child pairs are retrieved in blocks via findByUUID(Set<UUID>) from CDM DB. 
428 	 */
429 	private boolean createParentChildRelationships(FaunaEuropaeaImportState state, Map<UUID, UUID> childParentMap) {
430 		//gets the taxon "Hydroscaphidae"(family)
431 		TaxonBase taxon = getTaxonService().find(UUID.fromString(acceptedTaxonUUID));
432 		sourceRef = taxon.getSec();
433 		boolean success = true;
434 		int limit = state.getConfig().getLimitSave();
435 		
436 			TaxonomicTree tree = getTaxonomicTreeFor(state, sourceRef);
437 			
438 			Set<TaxonBase> childSet = new HashSet<TaxonBase>(limit);
439 			
440 			Set<UUID> childKeysSet = childParentMap.keySet();
441 			Set<UUID> parentValuesSet = new HashSet<UUID>(childParentMap.values());
442 			
443 			if (logger.isTraceEnabled()) {
444 				logger.trace("Start reading children and parents");
445 			}
446 			List<TaxonBase> children = getTaxonService().find(childKeysSet);
447 			List<TaxonBase> parents = getTaxonService().find(parentValuesSet);
448 			Map<UUID, TaxonBase> parentsMap = new HashMap<UUID, TaxonBase>(parents.size());
449 			for (TaxonBase taxonBase : parents){
450 				parentsMap.put(taxonBase.getUuid(), taxonBase);
451 			}
452 			
453 			if (logger.isTraceEnabled()) {
454 				logger.debug("End reading children and parents");
455 				for (UUID uuid : childKeysSet) {
456 					logger.trace("child uuid query: " + uuid);
457 				}
458 				for (UUID uuid : parentValuesSet) {
459 					logger.trace("parent uuid query: " + uuid);
460 				}
461 				for (TaxonBase tb : children) {
462 					logger.trace("child uuid result: " + tb.getUuid());
463 				}
464 				for (TaxonBase tb : parents) {
465 					logger.trace("parent uuid result: " + tb.getUuid());
466 				}
467 			}
468 
469 			UUID mappedParentUuid = null;
470 			UUID childUuid = null;
471 
472 			for (TaxonBase child : children) {
473 
474 				try {
475 					Taxon childTaxon = child.deproxy(child, Taxon.class);
476 					childUuid = childTaxon.getUuid();
477 					mappedParentUuid = childParentMap.get(childUuid);
478 					TaxonBase parent = null;
479 					
480 					TaxonBase potentialParent = parentsMap.get(mappedParentUuid);
481 //					for (TaxonBase potentialParent : parents ) {
482 //						parentUuid = potentialParent.getUuid();
483 //						if(parentUuid.equals(mappedParentUuid)) {
484 							parent = potentialParent;
485 							if (logger.isDebugEnabled()) {
486 								logger.debug("Parent (" + mappedParentUuid + ") found for child (" + childUuid + ")");
487 							}
488 //							break;
489 //						}
490 //					}
491 					
492 					Taxon parentTaxon = parent.deproxy(parent, Taxon.class);
493 					
494 					if (childTaxon != null && parentTaxon != null) {
495 						
496 						tree.addParentChild(parentTaxon, childTaxon, sourceRef, null);
497 						
498 						if (logger.isDebugEnabled()) {
499 							logger.debug("Parent-child (" + mappedParentUuid + "-" + childUuid + 
500 							") relationship created");
501 						}
502 						if (childTaxon != null && !childSet.contains(childTaxon)) {
503 							
504 							childSet.add(childTaxon);
505 							
506 							if (logger.isTraceEnabled()) {
507 								logger.trace("Child taxon (" + childUuid + ") added to Set");
508 							}
509 							
510 						} else {
511 							if (logger.isDebugEnabled()) {
512 								logger.debug("Duplicated child taxon (" + childUuid + ")");
513 							}
514 						}
515 					} else {
516 						if (logger.isDebugEnabled()) {
517 							logger.debug("Parent(" + mappedParentUuid + ") or child (" + childUuid + " is null");
518 						}
519 					}
520 					
521 				} catch (Exception e) {
522 					logger.error("Error creating taxonomically included relationship parent-child (" + 
523 						mappedParentUuid + " <----> " + childUuid + ")", e);
524 				}
525 
526 			}
527 			if (logger.isTraceEnabled()) {
528 				logger.trace("Start saving childSet");
529 			}
530 			getTaxonService().save(childSet);
531 			if (logger.isTraceEnabled()) {
532 				logger.trace("End saving childSet");
533 			}
534 
535 			parentValuesSet = null;
536 			childSet = null;
537 			children = null;
538 			parents = null;
539 			tree = null;
540 		
541 		return success;
542 	}
543 
544 	/* Creates misapplied name relationships.
545 	 * Misapplied name-accepted taxon pairs are retrieved in blocks via findByUUID(Set<UUID>) from CDM DB. 
546 	 */
547 	private boolean createMisappliedNameRelationships(FaunaEuropaeaImportState state, Map<UUID, UUID> fromToMap) {
548 
549 		//gets the taxon "Hydroscaphidae" (family)
550 		
551 		TaxonBase taxon = getTaxonService().find(UUID.fromString(acceptedTaxonUUID));
552 		sourceRef = taxon.getSec();
553 		boolean success = true;
554 		int limit = state.getConfig().getLimitSave();
555 		
556 			Set<TaxonBase> misappliedNameSet = new HashSet<TaxonBase>(limit);
557 			
558 			Set<UUID> misappliedNamesSet = fromToMap.keySet();
559 			Set<UUID> acceptedTaxaSet = new HashSet<UUID>(fromToMap.values());
560 			
561 			if (logger.isTraceEnabled()) {
562 				logger.trace("Start reading misapplied names and accepted taxa");
563 			}
564 			List<TaxonBase> misappliedNames = getTaxonService().find(misappliedNamesSet);
565 			List<TaxonBase> acceptedTaxa = getTaxonService().find(acceptedTaxaSet);
566 			Map<UUID, TaxonBase> acceptedTaxaMap = new HashMap<UUID, TaxonBase>(acceptedTaxa.size());
567 			for (TaxonBase taxonBase : acceptedTaxa){
568 				acceptedTaxaMap.put(taxonBase.getUuid(), taxonBase);
569 			}
570 			
571 			if (logger.isTraceEnabled()) {
572 				logger.info("End reading misapplied names and accepted taxa");
573 				for (UUID uuid : misappliedNamesSet) {
574 					logger.trace("misapplied name uuid query: " + uuid);
575 				}
576 				for (UUID uuid : acceptedTaxaSet) {
577 					logger.trace("accepted taxon uuid query: " + uuid);
578 				}
579 				for (TaxonBase tb : misappliedNames) {
580 					logger.trace("misapplied name uuid result: " + tb.getUuid());
581 				}
582 				for (TaxonBase tb : acceptedTaxa) {
583 					logger.trace("accepted taxon uuid result: " + tb.getUuid());
584 				}
585 			}
586 
587 			UUID mappedAcceptedTaxonUuid = null;
588 			UUID misappliedNameUuid = null;
589 			Taxon misappliedNameTaxon = null;
590 			TaxonBase acceptedTaxonBase = null;
591 			Taxon acceptedTaxon = null;
592 
593 			for (TaxonBase misappliedName : misappliedNames) {
594 
595 				try {
596 					misappliedNameTaxon = misappliedName.deproxy(misappliedName, Taxon.class);
597 					misappliedNameUuid = misappliedNameTaxon.getUuid();
598 					mappedAcceptedTaxonUuid = fromToMap.get(misappliedNameUuid);
599 					acceptedTaxonBase = null;
600 					
601 					acceptedTaxonBase = acceptedTaxaMap.get(mappedAcceptedTaxonUuid);
602 							if (logger.isDebugEnabled()) {
603 								logger.debug("Parent (" + mappedAcceptedTaxonUuid + ") found for child (" + misappliedNameUuid + ")");
604 							}
605 					
606 							acceptedTaxon = acceptedTaxonBase.deproxy(acceptedTaxonBase, Taxon.class);
607 					
608 					if (misappliedNameTaxon != null && acceptedTaxon != null) {
609 						
610 						acceptedTaxon.addMisappliedName(misappliedNameTaxon, sourceRef, null);
611 					
612 						if (logger.isDebugEnabled()) {
613 							logger.debug("Accepted taxon / misapplied name (" + mappedAcceptedTaxonUuid + "-" + misappliedNameUuid + 
614 							") relationship created");
615 						}
616 						if (!misappliedNameSet.contains(misappliedNameTaxon)) {
617 							
618 							misappliedNameSet.add(misappliedNameTaxon);
619 							
620 							if (logger.isTraceEnabled()) {
621 								logger.trace("Misapplied name taxon (" + misappliedNameUuid + ") added to Set");
622 							}
623 							
624 						} else {
625 							if (logger.isDebugEnabled()) {
626 								logger.debug("Duplicated misapplied name taxon (" + misappliedNameUuid + ")");
627 							}
628 						}
629 					} else {
630 						if (logger.isDebugEnabled()) {
631 							logger.debug("Accepted taxon (" + mappedAcceptedTaxonUuid + ") or misapplied name (" + misappliedNameUuid + " is null");
632 						}
633 					}
634 					
635 					if (misappliedNameTaxon != null && !misappliedNameSet.contains(misappliedNameTaxon)) {
636 						misappliedNameSet.add(misappliedNameTaxon);
637 						if (logger.isTraceEnabled()) {
638 							logger.trace("Misapplied name taxon (" + misappliedNameUuid + ") added to Set");
639 						}
640 					} else {
641 						if (logger.isDebugEnabled()) {
642 							logger.debug("Duplicated misapplied name taxon (" + misappliedNameUuid + ")");
643 						}
644 					}
645 					
646 				} catch (Exception e) {
647 					logger.error("Error creating misapplied name relationship accepted taxon-misapplied name (" + 
648 						mappedAcceptedTaxonUuid + "-" + misappliedNameUuid + ")", e);
649 				}
650 
651 			}
652 			if (logger.isTraceEnabled()) {
653 				logger.trace("Start saving misappliedNameSet");
654 			}
655 			getTaxonService().save(misappliedNameSet);
656 			if (logger.isTraceEnabled()) {
657 				logger.trace("End saving misappliedNameSet");
658 			}
659 
660 			acceptedTaxaSet = null;
661 			misappliedNameSet = null;
662 			misappliedNames = null;
663 			acceptedTaxa = null;
664 		
665 		return success;
666 	}
667 
668 	
669 	/* Creates heterotypic synonym relationships.
670 	 * Synonym-accepted taxon pairs are retrieved in blocks via findByUUID(Set<UUID>) from CDM DB. 
671 	 */
672 	private boolean createHeterotypicSynonyms(FaunaEuropaeaImportState state, Map<UUID, UUID> fromToMap) {
673 
674 		int limit = state.getConfig().getLimitSave();
675 		boolean success = true;
676 
677 		Set<TaxonBase> synonymSet = new HashSet<TaxonBase>(limit);
678 
679 		Set<UUID> synonymUuidSet = fromToMap.keySet();
680 		Set<UUID> acceptedTaxaUuidSet = new HashSet<UUID>(fromToMap.values());
681 
682 		if (logger.isTraceEnabled()) {
683 			logger.trace("Reading synonym names and accepted taxa...");
684 		}
685 		List<TaxonBase> synonyms = getTaxonService().find(synonymUuidSet);
686 		List<TaxonBase> acceptedTaxa = getTaxonService().find(acceptedTaxaUuidSet);
687 		Map<UUID, TaxonBase> acceptedTaxaMap = new HashMap<UUID, TaxonBase>(acceptedTaxa.size());
688 		for (TaxonBase taxonBase : acceptedTaxa){
689 			acceptedTaxaMap.put(taxonBase.getUuid(), taxonBase);
690 		}
691 
692 		if (logger.isTraceEnabled()) {
693 			logger.trace("End reading synonyms names and accepted taxa");
694 			for (UUID uuid : synonymUuidSet) {
695 				logger.trace("synonym uuid query: " + uuid);
696 			}
697 			for (UUID uuid : acceptedTaxaUuidSet) {
698 				logger.trace("accepted taxon uuid query: " + uuid);
699 			}
700 			for (TaxonBase tb : synonyms) {
701 				logger.trace("synonym uuid result: " + tb.getUuid());
702 			}
703 			for (TaxonBase tb : acceptedTaxa) {
704 				logger.trace("accepted taxon uuid result: " + tb.getUuid());
705 			}
706 		}
707 
708 		UUID mappedAcceptedTaxonUuid = null;
709 		UUID synonymUuid = null;
710 		Synonym synonym = null;
711 		TaxonBase acceptedTaxonBase = null;
712 		Taxon acceptedTaxon = null;
713 
714 		for (TaxonBase synonymTaxonBase : synonyms) {
715 
716 			try {
717 				synonym = synonymTaxonBase.deproxy(synonymTaxonBase, Synonym.class);
718 				synonymUuid = synonym.getUuid();
719 				mappedAcceptedTaxonUuid = fromToMap.get(synonymUuid);
720 				acceptedTaxonBase = null;
721 
722 				acceptedTaxonBase = acceptedTaxaMap.get(mappedAcceptedTaxonUuid);
723 				if (logger.isDebugEnabled()) {
724 					logger.debug("Parent (" + mappedAcceptedTaxonUuid + ") found for child (" + synonymUuid + ")");
725 				}
726 				acceptedTaxon = acceptedTaxonBase.deproxy(acceptedTaxonBase, Taxon.class);
727 
728 				if (synonym != null && acceptedTaxon != null) {
729 
730 					//TODO: in case original genus exists must add synonym to original genus instead of to accepted taxon
731 					acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.HETEROTYPIC_SYNONYM_OF());
732 
733 					if (logger.isDebugEnabled()) {
734 						logger.debug("Accepted taxon - synonym (" + mappedAcceptedTaxonUuid + " - " + synonymUuid + 
735 						") relationship created");
736 					}
737 					if (synonym != null && !synonymSet.contains(synonym)) {
738 
739 						synonymSet.add(synonym);
740 
741 						if (logger.isTraceEnabled()) {
742 							logger.trace("Synonym (" + synonymUuid + ") added to Set");
743 						}
744 
745 					} else {
746 						if (logger.isDebugEnabled()) {
747 							logger.debug("Duplicated synonym (" + synonymUuid + ")");
748 						}
749 					}
750 				} else {
751 					if (logger.isDebugEnabled()) {
752 						logger.debug("Accepted taxon (" + mappedAcceptedTaxonUuid + ") or misapplied name (" + synonymUuid + " is null");
753 					}
754 				}
755 			} catch (Exception e) {
756 				logger.error("Error creating synonym relationship: accepted taxon-synonym (" + 
757 						mappedAcceptedTaxonUuid + "-" + synonymUuid + ")", e);
758 			}
759 		}
760 		if (logger.isTraceEnabled()) {
761 			logger.trace("Start saving synonymSet");
762 		}
763 		getTaxonService().save(synonymSet);
764 		if (logger.isTraceEnabled()) {
765 			logger.trace("End saving synonymSet");
766 		}
767 
768 		acceptedTaxaUuidSet = null;
769 		synonymSet = null;
770 		synonyms = null;
771 		acceptedTaxa = null;
772 
773 		return success;
774 	}
775 
776 }