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  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.P_PARENTHESIS;
14  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_GENUS;
15  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_SPECIES;
16  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_SUBGENUS;
17  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.R_SUBSPECIES;
18  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.T_STATUS_ACCEPTED;
19  import static eu.etaxonomy.cdm.io.faunaEuropaea.FaunaEuropaeaTransformer.T_STATUS_NOT_ACCEPTED;
20  
21  import java.sql.ResultSet;
22  import java.sql.SQLException;
23  import java.util.Collection;
24  import java.util.HashMap;
25  import java.util.HashSet;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.UUID;
29  import java.util.regex.Matcher;
30  import java.util.regex.Pattern;
31  
32  import org.apache.log4j.Logger;
33  import org.springframework.stereotype.Component;
34  import org.springframework.transaction.TransactionStatus;
35  
36  import eu.etaxonomy.cdm.common.CdmUtils;
37  import eu.etaxonomy.cdm.io.common.ICdmIO;
38  import eu.etaxonomy.cdm.io.common.ImportHelper;
39  import eu.etaxonomy.cdm.io.common.MapWrapper;
40  import eu.etaxonomy.cdm.io.common.Source;
41  import eu.etaxonomy.cdm.io.pesi.out.PesiTransformer;
42  import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
43  import eu.etaxonomy.cdm.model.common.CdmBase;
44  import eu.etaxonomy.cdm.model.common.Extension;
45  import eu.etaxonomy.cdm.model.common.ExtensionType;
46  import eu.etaxonomy.cdm.model.common.IdentifiableSource;
47  import eu.etaxonomy.cdm.model.name.Rank;
48  import eu.etaxonomy.cdm.model.name.TaxonNameBase;
49  import eu.etaxonomy.cdm.model.name.ZoologicalName;
50  import eu.etaxonomy.cdm.model.reference.ReferenceBase;
51  import eu.etaxonomy.cdm.model.taxon.Synonym;
52  import eu.etaxonomy.cdm.model.taxon.Taxon;
53  import eu.etaxonomy.cdm.model.taxon.TaxonBase;
54  import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
55  
56  
57  /**
58   * @author a.babadshanjan
59   * @created 12.05.2009
60   * @version 1.0
61   */
62  @Component
63  public class FaunaEuropaeaTaxonNameImport extends FaunaEuropaeaImportBase  {
64  	
65  	public static final String OS_NAMESPACE_TAXON = "Taxon";
66  	private static final Logger logger = Logger.getLogger(FaunaEuropaeaTaxonNameImport.class);
67  
68  	/* Max number of taxa to retrieve (for test purposes) */
69  	private int maxTaxa = 0;
70  
71  	/* (non-Javadoc)
72  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IImportConfigurator)
73  	 */
74  	@Override
75  	protected boolean doCheck(FaunaEuropaeaImportState state) {
76  		boolean result = true;
77  		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
78  		logger.warn("Checking for Taxa not yet fully implemented");
79  		result &= checkTaxonStatus(fauEuConfig);
80  		
81  		return result;
82  	}
83  	
84  	/* (non-Javadoc)
85  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
86  	 */
87  	protected boolean isIgnore(FaunaEuropaeaImportState state) {
88  		return ! state.getConfig().isDoTaxa();
89  	}
90  
91  	private boolean checkTaxonStatus(FaunaEuropaeaImportConfigurator fauEuConfig) {
92  		boolean result = true;
93  //		try {
94  			Source source = fauEuConfig.getSource();
95  			String sqlStr = "";
96  			ResultSet rs = source.getResultSet(sqlStr);
97  			return result;
98  //		} catch (SQLException e) {
99  //			e.printStackTrace();
100 //			return false;
101 //		}
102 	}
103 	
104 	/** 
105 	 * Import taxa from FauEU DB
106 	 */
107 	protected boolean doInvoke(FaunaEuropaeaImportState state) {				
108 		
109 		boolean success = true;
110 		if(logger.isInfoEnabled()) { logger.info("Start making taxa..."); }
111 		
112 		
113 		
114 		success = processTaxa(state);
115 		
116 		logger.info("End making taxa...");
117 		return success;
118 	}
119 
120 	/**
121 	 * Returns the ExtensionType for a given UUID.
122 	 * @param uuid
123 	 * @param label
124 	 * @param text
125 	 * @param labelAbbrev
126 	 * @return
127 	 */
128 	protected ExtensionType getExtensionType(UUID uuid, String label, String text, String labelAbbrev){
129 		ExtensionType extensionType = (ExtensionType)getTermService().find(uuid);
130 		if (extensionType == null) {
131 			extensionType = ExtensionType.NewInstance(label, text, labelAbbrev);
132 			extensionType.setUuid(uuid);
133 //			annotationType.setVocabulary(AnnotationType.EDITORIAL().getVocabulary());
134 			getTermService().save(extensionType);
135 		}
136 		return extensionType;
137 	}
138 
139 	/**
140 	 * Returns an empty string in case of a null string.
141 	 * This avoids having the string "null" when using StringBuilder.append(null);
142 	 * @param string
143 	 * @return
144 	 */
145 	private String NullToEmpty(String string) {
146 		if (string == null) {
147 			return "";
148 		} else {
149 			return string;
150 		}
151 	}
152 
153 	/** Retrieve taxa from FauEu DB, process in blocks */
154 	private boolean processTaxa(FaunaEuropaeaImportState state) {
155 
156 		int limit = state.getConfig().getLimitSave();
157 
158 		TransactionStatus txStatus = null;
159 
160 		Map<String, MapWrapper<? extends CdmBase>> stores = state.getStores();
161 		MapWrapper<TeamOrPersonBase> authorStore = (MapWrapper<TeamOrPersonBase>)stores.get(ICdmIO.TEAM_STORE);
162 		
163 		Map<Integer, TaxonBase<?>> taxonMap = null;
164 		Map<Integer, FaunaEuropaeaTaxon> fauEuTaxonMap = null;
165 		/* Store for heterotypic synonyms to be save separately */
166 		Set<Synonym> synonymSet = null;
167 
168 		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
169 		ReferenceBase<?> sourceRef = fauEuConfig.getSourceReference();
170 
171 		Source source = fauEuConfig.getSource();
172 		int i = 0;
173 		boolean success = true;
174 
175 		String selectCount = 
176 			" SELECT count(*) ";
177 
178 		String selectColumns = 
179 			" SELECT Parent.TAX_NAME AS P2Name, Parent.TAX_RNK_ID AS P2RankId, " +
180 			" GrandParent.TAX_ID AS GP3Id, GrandParent.TAX_NAME AS GP3Name, GrandParent.TAX_RNK_ID AS GP3RankId, " +
181 			" GreatGrandParent.TAX_ID AS GGP4Id, GreatGrandParent.TAX_NAME AS GGP4Name, GreatGrandParent.TAX_RNK_ID AS GGP4RankId, " +
182 			" GreatGreatGrandParent.TAX_ID AS GGGP5Id, GreatGreatGrandParent.TAX_NAME AS GGGP5Name, GreatGreatGrandParent.TAX_RNK_ID AS GGGP5RankId, " +
183 			" OriginalGenusTaxon.TAX_NAME AS OGenusName, " +
184 			" GreatGreatGreatGrandParent.TAX_ID AS GGGGP6Id, GreatGreatGreatGrandParent.TAX_NAME AS GGGGP6Name, GreatGreatGreatGrandParent.TAX_RNK_ID AS GGGGP6RankId," +
185 			" expertUsers.usr_id AS expertUserId, expertUsers.usr_title AS ExpertUsrTitle, expertUsers.usr_firstname AS ExpertUsrFirstname, expertUsers.usr_lastname AS ExpertUsrLastname," +
186 			" speciesExpertUsers.usr_id AS speciesExpertUserId, speciesExpertUsers.usr_title AS SpeciesUsrTitle, speciesExpertUsers.usr_firstname AS SpeciesUsrFirstname, speciesExpertUsers.usr_lastname AS SpeciesUsrLastname," +
187 			" Taxon.*, rank.*, author.* ";
188 		
189 		String fromClause = 
190 			" FROM Taxon LEFT OUTER JOIN " +
191 			" Taxon AS Parent ON Taxon.TAX_TAX_IDPARENT = Parent.TAX_ID LEFT OUTER JOIN " +
192 			" Taxon AS GrandParent ON Parent.TAX_TAX_IDPARENT = GrandParent.TAX_ID LEFT OUTER JOIN " +
193 			" Taxon AS GreatGrandParent ON GrandParent.TAX_TAX_IDPARENT = GreatGrandParent.TAX_ID LEFT OUTER JOIN " +
194 			" Taxon AS GreatGreatGrandParent ON GreatGrandParent.TAX_TAX_IDPARENT = GreatGreatGrandParent.TAX_ID LEFT OUTER JOIN " +
195 			" Taxon AS GreatGreatGreatGrandParent ON GreatGreatGrandParent.TAX_TAX_IDPARENT = GreatGreatGreatGrandParent.TAX_ID LEFT OUTER JOIN " +
196 			" Taxon AS OriginalGenusTaxon ON Taxon.TAX_TAX_IDGENUS = OriginalGenusTaxon.TAX_ID LEFT OUTER JOIN " +
197 			" author ON Taxon.TAX_AUT_ID = author.aut_id LEFT OUTER JOIN " +
198 			" users AS expertUsers ON Taxon.TAX_USR_IDGC = expertUsers.usr_id LEFT OUTER JOIN " +
199 			" users AS speciesExpertUsers ON Taxon.TAX_USR_IDSP = speciesExpertUsers.usr_id LEFT OUTER JOIN " +
200 			" rank ON Taxon.TAX_RNK_ID = rank.rnk_id ";
201 
202 		String countQuery = 
203 			selectCount + fromClause;
204 
205 		String selectQuery = 
206 			selectColumns + fromClause;
207 		
208 
209         try {
210 
211 			ResultSet rs = source.getResultSet(countQuery);
212 			rs.next();
213 			int count = rs.getInt(1);
214 			
215 			rs = source.getResultSet(selectQuery);
216 
217 	        if (logger.isInfoEnabled()) {
218 				logger.info("Number of rows: " + count);
219 				logger.info("Count Query: " + countQuery);
220 				logger.info("Select Query: " + selectQuery);
221 			}
222 	        
223 			while (rs.next()) {
224 
225 				if ((i++ % limit) == 0) {
226 					
227 					txStatus = startTransaction();
228 					taxonMap = new HashMap<Integer, TaxonBase<?>>(limit);
229 					fauEuTaxonMap = new HashMap<Integer, FaunaEuropaeaTaxon>(limit);
230 					synonymSet = new HashSet<Synonym>();
231 					
232 					if(logger.isInfoEnabled()) {
233 						logger.info("i = " + i + " - Transaction started"); 
234 					}
235 				}
236 
237 				String localName = rs.getString("TAX_NAME");
238 				String parentName = rs.getString("P2Name");
239 				int grandParentId = rs.getInt("GP3Id");
240 				String grandParentName = rs.getString("GP3Name");
241 				int greatGrandParentId = rs.getInt("GGP4Id");
242 				String greatGrandParentName = rs.getString("GGP4Name");
243 				int greatGreatGrandParentId = rs.getInt("GGGP5Id");
244 				String greatGreatGrandParentName = rs.getString("GGGP5Name");
245 				String greatGreatGreatGrandParentName = rs.getString("GGGGP6Name");
246 				String originalGenusName = rs.getString("OGenusName");
247 				String autName = rs.getString("aut_name");
248 				int taxonId = rs.getInt("TAX_ID");
249 				int rankId = rs.getInt("TAX_RNK_ID");
250 				int parentId = rs.getInt("TAX_TAX_IDPARENT");
251 				int parentRankId = rs.getInt("P2RankId");
252 				int grandParentRankId = rs.getInt("GP3RankId");
253 				int greatGrandParentRankId = rs.getInt("GGP4RankId");
254 				int greatGreatGrandParentRankId = rs.getInt("GGGP5RankId");
255 				int greatGreatGreatGrandParentRankId = rs.getInt("GGGGP6RankId");
256 				int originalGenusId = rs.getInt("TAX_TAX_IDGENUS");
257 				int autId = rs.getInt("TAX_AUT_ID");
258 				int status = rs.getInt("TAX_VALID");
259 
260 				// user related
261 				String expertUsrTitle = rs.getString("ExpertUsrTitle");
262 				String expertUsrFirstname = rs.getString("ExpertUsrFirstname");
263 				String expertUsrLastname = rs.getString("ExpertUsrLastname");
264 				String speciesUsrTitle = rs.getString("SpeciesUsrTitle");
265 				String speciesUsrFirstname = rs.getString("SpeciesUsrFirstname");
266 				String speciesUsrLastname = rs.getString("SpeciesUsrLastname");
267 				String expertUserId = "" + rs.getInt("expertUserId");
268 				String speciesExpertUserId = "" + rs.getInt("speciesExpertUserId");
269 
270 				String expertName = "";
271 				if (expertUsrTitle != null) {
272 					expertName = expertUsrTitle;
273 					if (! expertUsrTitle.endsWith(".")) {
274 						expertName += ".";
275 					}
276 				}
277 				expertName += expertUsrTitle == null ? NullToEmpty(expertUsrFirstname) : " " + NullToEmpty(expertUsrFirstname);
278 				if ((expertUsrTitle != null || expertUsrFirstname != null) && expertUsrLastname != null) {
279 					expertName += " " + expertUsrLastname;
280 				}
281 				
282 				String speciesExpertName = speciesUsrTitle == null ? "" : speciesUsrTitle + ".";
283 				if (speciesUsrTitle != null) {
284 					speciesExpertName = speciesUsrTitle;
285 					if (! speciesUsrTitle.endsWith(".")) {
286 						speciesExpertName += ".";
287 					}
288 				}
289 				speciesExpertName += speciesUsrTitle == null ? NullToEmpty(speciesUsrFirstname) : " " + NullToEmpty(speciesUsrFirstname);
290 				if ((speciesUsrTitle != null || speciesUsrFirstname != null) && speciesUsrLastname != null) {
291 					speciesExpertName += " " + speciesUsrLastname;
292 				}
293 				
294 				// date related
295 				String createdDate = rs.getString("TAX_CREATEDAT");
296 				String modifiedDate = rs.getString("TAX_MODIFIEDAT");
297 				String lastAction = createdDate.equals(modifiedDate) ? "created" : "modified";
298 				String lastActionDate = createdDate.equals(modifiedDate) ? createdDate : modifiedDate;
299 				
300 				// note related
301 				String taxComment = rs.getString("TAX_TAXCOMMENT");
302 				String fauComment = rs.getString("TAX_FAUCOMMENT");
303 				String fauExtraCodes = rs.getString("TAX_FAUEXTRACODES");
304 
305 				// Avoid publication year 0 for NULL values in database.
306 				Integer year = rs.getInt("TAX_YEAR");
307 				if (year != null && year.intValue() == 0) {
308 					year = null;
309 				}
310 				
311 				//int familyId = rs.getInt("TAX_TAX_IDFAMILY");
312 
313 				Rank rank = null;
314 				int parenthesis = rs.getInt("TAX_PARENTHESIS");
315 				UUID taxonBaseUuid = null;
316 				if (resultSetHasColumn(rs,"UUID")){
317 					taxonBaseUuid = UUID.fromString(rs.getString("UUID"));
318 				} else {
319 					taxonBaseUuid = UUID.randomUUID();
320 				}
321 
322 				FaunaEuropaeaTaxon fauEuTaxon = new FaunaEuropaeaTaxon();
323 				fauEuTaxon.setUuid(taxonBaseUuid);
324 				fauEuTaxon.setId(taxonId);
325 				fauEuTaxon.setRankId(rankId);
326 				fauEuTaxon.setLocalName(localName);
327 				
328 				fauEuTaxon.setParentId(parentId);
329 				fauEuTaxon.setParentRankId(parentRankId);
330 				fauEuTaxon.setParentName(parentName);
331 				
332 				fauEuTaxon.setGrandParentId(grandParentId);
333 				fauEuTaxon.setGrandParentRankId(grandParentRankId);
334 				fauEuTaxon.setGrandParentName(grandParentName);
335 				
336 				fauEuTaxon.setGreatGrandParentId(greatGrandParentId);
337 				fauEuTaxon.setGreatGrandParentRankId(greatGrandParentRankId);
338 				fauEuTaxon.setGreatGrandParentName(greatGrandParentName);
339 				
340 				fauEuTaxon.setGreatGreatGrandParentId(greatGreatGrandParentId);
341 				fauEuTaxon.setGreatGreatGrandParentRankId(greatGreatGrandParentRankId);
342 				fauEuTaxon.setGreatGreatGrandParentName(greatGreatGrandParentName);
343 				
344 				fauEuTaxon.setGreatGreatGreatGrandParentRankId(greatGreatGreatGrandParentRankId);
345 				fauEuTaxon.setGreatGreatGreatGrandParentName(greatGreatGreatGrandParentName);
346 				
347 				fauEuTaxon.setOriginalGenusId(originalGenusId);
348 				fauEuTaxon.setYear(year);
349 				fauEuTaxon.setOriginalGenusName(originalGenusName);
350 				fauEuTaxon.setAuthorName(autName);
351 				if (parenthesis == P_PARENTHESIS) {
352 					fauEuTaxon.setParenthesis(true);
353 				} else {
354 					fauEuTaxon.setParenthesis(false);
355 				}
356 				if (status == T_STATUS_ACCEPTED) {
357 					fauEuTaxon.setValid(true);
358 				} else {
359 					fauEuTaxon.setValid(false);
360 				}
361 
362 //				fauEuTaxon.setAuthorId(autId);
363 
364 				try {
365 					rank = FaunaEuropaeaTransformer.rankId2Rank(rs, false);
366 				} catch (UnknownCdmTypeException e) {
367 					logger.warn("Taxon (" + taxonId + ") has unknown rank (" + rankId + ") and could not be saved.");
368 					continue;
369 				} catch (NullPointerException e) {
370 					logger.warn("Taxon (" + taxonId + ") has rank null and can not be saved.");
371 					continue;
372 				}
373 
374 				ReferenceBase<?> sourceReference = fauEuConfig.getSourceReference();
375 				ReferenceBase<?> auctReference = fauEuConfig.getAuctReference();
376 
377 				ZoologicalName zooName = ZoologicalName.NewInstance(rank);
378 				TeamOrPersonBase<?> author = authorStore.get(autId);
379 				
380 				zooName.setCombinationAuthorTeam(author);
381 				zooName.setPublicationYear(year);
382 				
383 				// Add UserId extensions to this zooName
384 				Extension.NewInstance(zooName, expertUserId, getExtensionType(PesiTransformer.expertUserIdUuid, "expertUserId", "expertUserId", "EUID"));
385 				Extension.NewInstance(zooName, speciesExpertUserId, getExtensionType(PesiTransformer.speciesExpertUserIdUuid, "speciesExpertUserId", "speciesExpertUserId", "SEUID"));
386 				
387 				// Add Expert extensions to this zooName
388 				Extension.NewInstance(zooName, expertName, getExtensionType(PesiTransformer.expertNameUuid, "ExpertName", "ExpertName", "EN"));
389 				Extension.NewInstance(zooName, speciesExpertName, getExtensionType(PesiTransformer.speciesExpertNameUuid, "SpeciesExpertName", "SpeciesExpertName", "SEN"));
390 
391 				// Add Date extensions to this zooName
392 				Extension.NewInstance(zooName, lastAction, getExtensionType(PesiTransformer.lastActionUuid, "LastAction", "LastAction", "LA"));
393 				Extension.NewInstance(zooName, lastActionDate, getExtensionType(PesiTransformer.lastActionDateUuid, "LastActionDate", "LastActionDate", "LAD"));
394 
395 				// Add Note extensions to this zooName
396 				Extension.NewInstance(zooName, taxComment, getExtensionType(PesiTransformer.taxCommentUuid, "TaxComment", "TaxComment", "TC"));
397 				Extension.NewInstance(zooName, fauComment, getExtensionType(PesiTransformer.fauCommentUuid, "FauComment", "FauComment", "FC"));
398 				Extension.NewInstance(zooName, fauExtraCodes, getExtensionType(PesiTransformer.fauExtraCodesUuid, "FauExtraCodes", "FauExtraCodes", "FEC"));
399 				
400 				TaxonBase<?> taxonBase;
401 
402 				Synonym synonym = null;
403 				Taxon taxon;
404 				try {
405 					// check for occurrence of the auct string in auctName
406 					String auctRegEx = "\\bauct\\.?\\b"; // The word "auct" with or without "."
407 					boolean auctWordFound = expressionMatches(auctRegEx, autName);
408 
409 					if (status == T_STATUS_ACCEPTED || auctWordFound) {
410 
411 						if (auctWordFound) { // misapplied name
412 							zooName.setCombinationAuthorTeam(null);
413 							zooName.setPublicationYear(null);
414 							taxon = Taxon.NewInstance(zooName, auctReference);
415 							if (logger.isDebugEnabled()) {
416 								logger.debug("Misapplied name created (" + taxonId + ")");
417 							}
418 						} else { // accepted taxon
419 							taxon = Taxon.NewInstance(zooName, sourceReference);
420 							if (logger.isDebugEnabled()) {
421 								logger.debug("Taxon created (" + taxonId + ")");
422 							}
423 						}
424 						taxonBase = taxon;
425 					} else if ((status == T_STATUS_NOT_ACCEPTED) && ! auctWordFound) { // synonym
426 						synonym = Synonym.NewInstance(zooName, sourceReference);
427 						//logger.info("Synonym created: " + synonym.getTitleCache() + " taxonName: " + zooName.getTitleCache());
428 						if (logger.isDebugEnabled()) {
429 							logger.debug("Synonym created (" + taxonId + ")");
430 						}
431 						taxonBase = synonym;
432 					} else {
433 						logger.warn("Unknown taxon status " + status + ". Taxon (" + taxonId + ") ignored.");
434 						continue;
435 					}
436 
437 					taxonBase.setUuid(taxonBaseUuid);
438 
439 					ImportHelper.setOriginalSource(taxonBase, fauEuConfig.getSourceReference(), taxonId, OS_NAMESPACE_TAXON);
440 					ImportHelper.setOriginalSource(zooName, fauEuConfig.getSourceReference(), taxonId, "TaxonName");
441 
442 					if (!taxonMap.containsKey(taxonId)) {
443 						if (taxonBase == null) {
444 							if (logger.isDebugEnabled()) { 
445 								logger.debug("Taxon base is null. Taxon (" + taxonId + ") ignored.");
446 							}
447 							continue;
448 						}
449 						taxonMap.put(taxonId, taxonBase);
450 						fauEuTaxonMap.put(taxonId, fauEuTaxon);
451 						
452 //						if (logger.isDebugEnabled()) { 
453 //						logger.debug("Stored taxon base (" + taxonId + ") " + localName); 
454 //						}
455 					} else {
456 						logger.warn("Not imported taxon base with duplicated TAX_ID (" + taxonId + 
457 								") " + localName);
458 					}
459 				} catch (Exception e) {
460 					logger.warn("An exception occurred when creating taxon base with id " + taxonId + 
461 					". Taxon base could not be saved.");
462 					e.printStackTrace();
463 				}
464 
465 				if (((i % limit) == 0 && i != 1 ) || i == count) { 
466 
467 					success = processTaxaSecondPass(state, taxonMap, fauEuTaxonMap, synonymSet);
468 					if(logger.isDebugEnabled()) { logger.debug("Saving taxa ..."); }
469 					getTaxonService().save((Collection)taxonMap.values());
470 					getTaxonService().save((Collection)synonymSet);
471 					
472 					taxonMap = null;
473 					synonymSet = null;
474 					fauEuTaxonMap = null;
475 					commitTransaction(txStatus);
476 					
477 					if(logger.isInfoEnabled()) {
478 						logger.info("i = " + i + " - Transaction committed"); 
479 					}
480 				}
481 
482 			}
483 		} catch (SQLException e) {
484 			logger.error("SQLException:" +  e);
485 			success = false;
486 		}
487 
488 		return success;
489 	}
490 
491 	/**
492 	 * Returns whether a regular expression is found in a given target string.
493 	 * @param regEx
494 	 * @param targetString
495 	 * @return
496 	 */
497 	private static boolean expressionMatches(String regEx, String targetString) {
498 		if (targetString == null) {
499 			return false;
500 		}
501 		Pattern pattern = Pattern.compile(regEx);
502 		Matcher matcher = pattern.matcher(targetString);
503 		if (matcher.find()) {
504 			return true;
505 		} else {
506 			return false;
507 		}
508 	}
509 	
510 	/**
511 	 * Processes taxa from complete taxon store
512 	 */
513 	private boolean processTaxaSecondPass(FaunaEuropaeaImportState state, Map<Integer, TaxonBase<?>> taxonMap,
514 			Map<Integer, FaunaEuropaeaTaxon> fauEuTaxonMap, Set<Synonym> synonymSet) {
515 
516 		if(logger.isDebugEnabled()) { logger.debug("Processing taxa second pass..."); }
517 
518 		FaunaEuropaeaImportConfigurator fauEuConfig = state.getConfig();
519 		
520 		boolean success = true;
521 
522 		for (int id : taxonMap.keySet())
523 		{
524 			if (logger.isDebugEnabled()) { logger.debug("Taxon # " + id); }
525 			
526 			TaxonBase<?> taxonBase = taxonMap.get(id);
527 			TaxonNameBase<?,?> taxonName = taxonBase.getName();
528 			FaunaEuropaeaTaxon fauEuTaxon = fauEuTaxonMap.get(id);
529 			boolean useOriginalGenus = false;
530 			if (taxonBase instanceof Synonym){
531 				useOriginalGenus = true;
532 			}
533 			
534 			String nameString = 
535 				buildTaxonName(fauEuTaxon, taxonBase, taxonName, useOriginalGenus, fauEuConfig);
536 			
537 			if (taxonBase instanceof Synonym){
538 				logger.info("Name of Synonym: " + nameString);
539 			}
540 			
541 			if (fauEuConfig.isDoBasionyms() 
542 					&& fauEuTaxon.getRankId() > R_SUBGENUS
543 					&& (fauEuTaxon.getOriginalGenusId() != 0)) {
544 				
545 				Integer originalGenusId = fauEuTaxon.getOriginalGenusId();
546 				Integer actualGenusId = getActualGenusId(fauEuTaxon);
547 				
548 				if (logger.isDebugEnabled()) {
549 					logger.debug("actual genus id = " + actualGenusId + ", original genus id = " + originalGenusId);
550 				}
551 				
552 				if (actualGenusId.intValue() != originalGenusId.intValue() && taxonBase.isInstanceOf(Taxon.class)) {
553 					success = createBasionym(fauEuTaxon, taxonBase, taxonName, fauEuConfig, synonymSet);
554 				} else if (fauEuTaxon.isParenthesis()) {
555 					//the authorteam should be set in parenthesis because there should be a basionym, but we do not know it?
556 					ZoologicalName zooName = taxonName.deproxy(taxonName, ZoologicalName.class);
557 					zooName.setBasionymAuthorTeam(zooName.getCombinationAuthorTeam());
558 					zooName.setCombinationAuthorTeam(null);
559 					zooName.setOriginalPublicationYear(zooName.getPublicationYear());
560 					zooName.setPublicationYear(null);
561 				}
562 				
563 			}
564 		}
565 		return success;	
566 	}
567 
568 	
569 	private boolean createBasionym(FaunaEuropaeaTaxon fauEuTaxon, TaxonBase<?> taxonBase, 
570 			TaxonNameBase<?,?>taxonName, FaunaEuropaeaImportConfigurator fauEuConfig,
571 			Set<Synonym> synonymSet) {
572 
573 		boolean success = true;
574 
575 		try {
576 			ZoologicalName zooName = taxonName.deproxy(taxonName, ZoologicalName.class);
577 			
578 			// create basionym
579 			ZoologicalName basionym = ZoologicalName.NewInstance(taxonName.getRank());
580 			basionym.setCombinationAuthorTeam(zooName.getCombinationAuthorTeam());
581 			
582 			zooName.setOriginalPublicationYear(zooName.getPublicationYear());
583 			basionym.setPublicationYear(zooName.getPublicationYear());
584 
585 			// add originalGenusId as source
586 			String originalGenusIdString = "" + fauEuTaxon.getId();
587 			IdentifiableSource basionymSource = IdentifiableSource.NewInstance(originalGenusIdString, "originalGenusId");
588 			basionym.addSource(basionymSource);
589 			
590 			// add original database reference
591 			ImportHelper.setOriginalSource(basionym, fauEuConfig.getSourceReference(), fauEuTaxon.getId(), "TaxonName");
592 			
593 			zooName.addBasionym(basionym, fauEuConfig.getSourceReference(), null, null);
594 			zooName.setBasionymAuthorTeam(zooName.getCombinationAuthorTeam());
595 			zooName.setCombinationAuthorTeam(null);
596 			zooName.setPublicationYear(null);
597 			zooName.setTitleCache(null); // This should (re)generate the titleCache automagically
598 			if (logger.isDebugEnabled()) {
599 				logger.debug("Basionym created (" + fauEuTaxon.getId() + ")");
600 			}
601 
602 			// create synonym
603 			Synonym synonym = Synonym.NewInstance(basionym, fauEuConfig.getSourceReference());
604 			
605 			if (fauEuTaxon.isValid()) { // Taxon
606 
607 				// homotypic synonym
608 				Taxon taxon = taxonBase.deproxy(taxonBase, Taxon.class);
609 				taxon.addHomotypicSynonym(synonym, fauEuConfig.getSourceReference(), null);
610 				if (logger.isDebugEnabled()) {
611 					logger.debug("Homotypic synonym created (" + fauEuTaxon.getId() + ")");
612 				}
613 
614 			} else { // Synonym
615 				
616 				// heterotypic synonym
617 				// synonym relationship to the accepted taxon is created later
618 				synonymSet.add(synonym);
619 				
620 				if (logger.isDebugEnabled()) {
621 					logger.debug("Heterotypic synonym stored (" + fauEuTaxon.getId() + ")");
622 				}
623 			}
624 			
625 			
626 			buildTaxonName(fauEuTaxon, synonym, basionym, true, fauEuConfig);
627 		} catch (Exception e) {
628 			logger.warn("Exception occurred when creating basionym for " + fauEuTaxon.getId());
629 			e.printStackTrace();
630 		}
631 		
632 		
633 		return success;
634 	}
635 	
636 	
637 	/* Build name title cache */
638 	private String buildNameTitleCache(String nameString, boolean useOriginalGenus, FaunaEuropaeaTaxon fauEuTaxon) {
639 		
640 		StringBuilder titleCacheStringBuilder = new StringBuilder(nameString);
641 		Integer year = fauEuTaxon.getYear();
642 		if (year != null) { // TODO: Ignore authors like xp, xf, etc?
643 			titleCacheStringBuilder.append(" ");
644 			if ((fauEuTaxon.isParenthesis() == true) && !useOriginalGenus) {
645 				titleCacheStringBuilder.append("(");
646 			}
647 			titleCacheStringBuilder.append(fauEuTaxon.getAuthor());
648 			titleCacheStringBuilder.append(" ");
649 			titleCacheStringBuilder.append(year);
650 			if ((fauEuTaxon.isParenthesis() == true) && !useOriginalGenus) {
651 				titleCacheStringBuilder.append(")");
652 			}
653 		}
654 		return titleCacheStringBuilder.toString();
655 	}
656 
657 
658 	/* Build taxon title cache */
659 	private String buildTaxonTitleCache(String nameCache, ReferenceBase<?> reference) {
660 		
661 		StringBuilder titleCacheStringBuilder = new StringBuilder(nameCache);
662 		titleCacheStringBuilder.append(" sec. ");
663 		titleCacheStringBuilder.append(reference.getTitleCache());
664 		return titleCacheStringBuilder.toString();
665 	}
666 
667 	
668 	/* Build name full title cache */
669 	private String buildNameFullTitleCache(String titleCache, FaunaEuropaeaImportConfigurator fauEuConfig) {
670 		
671 		StringBuilder fullTitleCacheStringBuilder = new StringBuilder(titleCache);
672 		fullTitleCacheStringBuilder.append(" ");
673 		fullTitleCacheStringBuilder.append(fauEuConfig.getSourceReferenceTitle());
674 		return fullTitleCacheStringBuilder.toString();
675 	}
676 	
677 	
678 	private String genusPart(StringBuilder originalGenusName, boolean useOriginalGenus, 
679 			StringBuilder genusOrUninomial) {
680 
681 		StringBuilder stringBuilder = new StringBuilder();
682 		
683 		if(useOriginalGenus) {
684 			stringBuilder.append(originalGenusName);
685 			genusOrUninomial.delete(0, genusOrUninomial.length());
686 			genusOrUninomial.append(originalGenusName);
687 		} else {
688 			stringBuilder.append(genusOrUninomial);
689 		}
690 		stringBuilder.append(" ");
691 
692 		return stringBuilder.toString();
693 	}
694 
695 	
696 	private String genusSubGenusPart(StringBuilder originalGenusName, boolean useOriginalGenus, 
697 			StringBuilder genusOrUninomial,
698 			StringBuilder infraGenericEpithet,
699 			FaunaEuropaeaTaxon fauEuTaxon) {
700 
701 		StringBuilder stringBuilder = new StringBuilder();
702 		
703 		stringBuilder.append(genusPart(originalGenusName, useOriginalGenus, genusOrUninomial));
704 
705 		// The infraGenericEpithet is set to empty only if the original genus should be used and
706 		// the actualGenusId is not the originalGenusId.
707 		// This differentiation is relevant for synonyms and for basionyms.
708 		// InfraGenericEpithets of accepted taxa are not touched at all.
709 		Integer originalGenusId = fauEuTaxon.getOriginalGenusId();
710 		Integer actualGenusId = getActualGenusId(fauEuTaxon);
711 		if (useOriginalGenus && 
712 				originalGenusId.intValue() != actualGenusId.intValue() && 
713 				originalGenusId.intValue() > 0 &&
714 				actualGenusId.intValue() > 0) {
715 			infraGenericEpithet.delete(0, infraGenericEpithet.length());
716 			stringBuilder.append(" ");
717 			return stringBuilder.toString();
718 		}
719 
720 		stringBuilder.append("(");
721 		stringBuilder.append(infraGenericEpithet);
722 		stringBuilder.append(")");
723 		stringBuilder.append(" ");
724 		
725 		return stringBuilder.toString();
726 	}
727 
728 	/** Get actual genus id **/
729 	private Integer getActualGenusId(FaunaEuropaeaTaxon fauEuTaxon) {
730 		Integer actualGenusId = null;
731 		HashMap<Integer, Integer> ranks = new HashMap<Integer, Integer>();
732 		ranks.put(fauEuTaxon.getParentRankId(), fauEuTaxon.getParentId());
733 		ranks.put(fauEuTaxon.getGrandParentRankId(), fauEuTaxon.getGrandParentId());
734 		ranks.put(fauEuTaxon.getGreatGrandParentRankId(), fauEuTaxon.getGreatGrandParentId());
735 		ranks.put(fauEuTaxon.getGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGrandParentId());
736 		ranks.put(fauEuTaxon.getGreatGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGreatGrandParentId());
737 		
738 		actualGenusId = ranks.get(R_GENUS);
739 
740 		return actualGenusId;
741 	}
742 	
743 	
744 	/** Build species and subspecies names */
745 	private String buildLowerTaxonName(StringBuilder originalGenus, boolean useOriginalGenus, 
746 			StringBuilder genusOrUninomial, StringBuilder infraGenericEpithet, 
747 			StringBuilder specificEpithet, StringBuilder infraSpecificEpithet,
748 			FaunaEuropaeaTaxon fauEuTaxon) {
749 		
750 		// species or subspecies name
751 		String localName = fauEuTaxon.getLocalName();
752 		int taxonId = fauEuTaxon.getId();
753 		int parentId = fauEuTaxon.getParentId();
754 		StringBuilder nameCacheStringBuilder = new StringBuilder();
755 
756 //		FaunaEuropaeaTaxon parent = fauEuTaxonMap.get(parentId);
757 		if (parentId == 0) {
758 			nameCacheStringBuilder.append(localName);
759 			if (logger.isInfoEnabled()) {
760 				logger.info("Parent of (" + taxonId + ") is null");
761 			}
762 			return nameCacheStringBuilder.toString();
763 		}
764 		
765 		String parentName = fauEuTaxon.getParentName();
766 		String grandParentName = fauEuTaxon.getGrandParentName();
767 		String greatGrandParentName = fauEuTaxon.getGreatGrandParentName();
768 		int rank = fauEuTaxon.getRankId();
769 		int parentRankId = fauEuTaxon.getParentRankId();
770 		int grandParentRankId = fauEuTaxon.getGrandParentRankId();
771 		int greatGrandParentRankId = fauEuTaxon.getGreatGrandParentRankId();
772 //		int grandParentId = fauEuTaxon.getGrandParentId();
773 //		int greatGrandParentId = grandParent.getParentId();
774 
775 		
776 		if (fauEuTaxon.isValid()) { // Taxon
777 			
778 			if (rank == R_SPECIES) {
779 
780 				if(parentRankId == R_SUBGENUS) {
781 					//differ between isParanthesis= true and false
782 					String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, 
783 							genusOrUninomial.append(grandParentName), 
784 							infraGenericEpithet.append(parentName),
785 							fauEuTaxon);
786 						nameCacheStringBuilder.append(genusSubGenusPart);
787 					
788 
789 				} else if(parentRankId == R_GENUS) {
790 
791 					String genusPart = genusPart(originalGenus, useOriginalGenus, 
792 							genusOrUninomial.append(parentName));
793 					nameCacheStringBuilder.append(genusPart);
794 				}
795 				nameCacheStringBuilder.append(localName);
796 				specificEpithet.append(localName);
797 
798 			} else if (rank == R_SUBSPECIES) {
799 
800 				if(grandParentRankId == R_SUBGENUS) {
801 
802 					String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, 
803 							genusOrUninomial.append(greatGrandParentName), 
804 							infraGenericEpithet.append(grandParentName),
805 							fauEuTaxon);
806 					nameCacheStringBuilder.append(genusSubGenusPart);
807 
808 				} else if (grandParentRankId == R_GENUS) {
809 
810 					String genusPart = genusPart(originalGenus, useOriginalGenus, 
811 							genusOrUninomial.append(grandParentName));
812 					nameCacheStringBuilder.append(genusPart);
813 
814 				}
815 				nameCacheStringBuilder.append(parentName);
816 				nameCacheStringBuilder.append(" ");
817 				nameCacheStringBuilder.append(localName);
818 				specificEpithet.append(parentName);
819 				infraSpecificEpithet.append(localName);
820 			}
821 		} else { // Synonym
822 			
823 			if (rank == R_SPECIES) {
824 
825 				if(grandParentRankId == R_SUBGENUS) {
826 					
827 					String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, 
828 							genusOrUninomial.append(greatGrandParentName), 
829 							infraGenericEpithet.append(grandParentName),
830 							fauEuTaxon);
831 					nameCacheStringBuilder.append(genusSubGenusPart);
832 
833 				} else if (grandParentRankId == R_GENUS) {
834 					
835 					String genusPart = genusPart(originalGenus, useOriginalGenus, 
836 							genusOrUninomial.append(grandParentName));
837 					nameCacheStringBuilder.append(genusPart);
838 
839 				}
840 				nameCacheStringBuilder.append(localName);
841 				specificEpithet.append(localName);
842 
843 			} else if (rank == R_SUBSPECIES) {
844 				
845 				String greatGreatGrandParentName = fauEuTaxon.getGreatGreatGrandParentName();
846 				
847 				if(greatGrandParentRankId == R_SUBGENUS) {
848 					
849 					String genusSubGenusPart = genusSubGenusPart(originalGenus, useOriginalGenus, 
850 							genusOrUninomial.append(greatGreatGrandParentName), 
851 							infraGenericEpithet.append(greatGrandParentName),
852 							fauEuTaxon);
853 					nameCacheStringBuilder.append(genusSubGenusPart);
854 					
855 				} else if (greatGrandParentRankId == R_GENUS) {
856 					
857 					String genusPart = genusPart(originalGenus, useOriginalGenus, 
858 							genusOrUninomial.append(greatGreatGrandParentName));
859 					nameCacheStringBuilder.append(genusPart);
860 				}
861 				
862 				nameCacheStringBuilder.append(grandParentName);
863 				nameCacheStringBuilder.append(" ");
864 				specificEpithet.append(grandParentName);
865 				nameCacheStringBuilder.append(localName);
866 				infraSpecificEpithet.append(localName);
867 			}
868 			
869 			
870 			
871 		}
872 		
873 		return nameCacheStringBuilder.toString();
874 	}
875 	
876 	
877 	/** Build taxon's name parts and caches */
878 	private String buildTaxonName(FaunaEuropaeaTaxon fauEuTaxon, TaxonBase<?> taxonBase, TaxonNameBase<?,?>taxonName,
879 			boolean useOriginalGenus, FaunaEuropaeaImportConfigurator fauEuConfig) {
880 
881 		/* Local taxon name string */
882 		String localString = "";
883 		/* Concatenated taxon name string */
884 		String completeString = "";
885 
886 		StringBuilder originalGenus = new StringBuilder("");
887 		
888 		StringBuilder genusOrUninomial = new StringBuilder();
889 		StringBuilder infraGenericEpithet = new StringBuilder(); 
890 		StringBuilder specificEpithet = new StringBuilder();
891 		StringBuilder infraSpecificEpithet = new StringBuilder();
892 
893 		localString = fauEuTaxon.getLocalName();
894 		int rank = fauEuTaxon.getRankId();
895 		
896 		// determine genus: this also works for cases of synonyms since the accepted taxon is its parent
897 		String originalGenusString = null;
898 		if (useOriginalGenus && ! "".equals(fauEuTaxon.getOriginalGenusName())) {
899 			originalGenusString  = fauEuTaxon.getOriginalGenusName();
900 		} else {
901 			originalGenusString = determineOriginalGenus(fauEuTaxon);
902 		}
903 
904 		if (originalGenusString != null) {
905 			originalGenus = new StringBuilder(originalGenusString);
906 		}
907 
908 		if(logger.isDebugEnabled()) { 
909 			logger.debug("Local taxon name (rank = " + rank + "): " + localString); 
910 		}
911 
912 		if (rank < R_SPECIES) {
913 			// subgenus or above
914 
915 			completeString = localString;
916 			if (rank == R_SUBGENUS) {
917 				// subgenus part
918 				infraGenericEpithet.append(localString);
919 				
920 				// genus part
921 				genusOrUninomial.append(originalGenus);
922 				
923 				completeString = originalGenus + " ("+ localString + ")";
924 			} else {
925 				// genus or above
926 				genusOrUninomial.append(localString);
927 			}
928 			
929 		} else {
930 			// species or below
931 
932 			taxonBase = taxonBase.deproxy(taxonBase, TaxonBase.class);
933 
934 			completeString = 
935 				buildLowerTaxonName(originalGenus, useOriginalGenus, 
936 						genusOrUninomial, infraGenericEpithet, specificEpithet, infraSpecificEpithet,
937 						fauEuTaxon);
938 			
939 			completeString = (String) CdmUtils.removeDuplicateWhitespace(completeString.trim());
940 
941 		}
942 		return setCompleteTaxonName(completeString, useOriginalGenus,
943 				genusOrUninomial.toString(), infraGenericEpithet.toString(), 
944 				specificEpithet.toString(), infraSpecificEpithet.toString(),
945 				fauEuTaxon, taxonBase, fauEuConfig);
946 		 
947 	}
948 	
949 	
950 	/**
951 	 * Determines the original genus name by searching the taxon with rank Genus.
952 	 * @param fauEuTaxon
953 	 * @return
954 	 */
955 	private String determineOriginalGenus(FaunaEuropaeaTaxon fauEuTaxon) {
956 		String originalGenus = null;
957 
958 		HashMap<Integer, String> ranks = new HashMap<Integer, String>();
959 		ranks.put(fauEuTaxon.getParentRankId(), fauEuTaxon.getParentName());
960 		ranks.put(fauEuTaxon.getGrandParentRankId(), fauEuTaxon.getGrandParentName());
961 		ranks.put(fauEuTaxon.getGreatGrandParentRankId(), fauEuTaxon.getGreatGrandParentName());
962 		ranks.put(fauEuTaxon.getGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGrandParentName());
963 		ranks.put(fauEuTaxon.getGreatGreatGreatGrandParentRankId(), fauEuTaxon.getGreatGreatGreatGrandParentName());
964 		
965 		originalGenus = ranks.get(R_GENUS);
966 
967 		return originalGenus;
968 	}
969 
970 	/** Sets name parts and caches */
971 	private String setCompleteTaxonName(String concatString, boolean useOriginalGenus,
972 			String genusOrUninomial, String infraGenericEpithet, String specificEpithet, String infraSpecificEpithet, 
973 			FaunaEuropaeaTaxon fauEuTaxon, TaxonBase<?> taxonBase, FaunaEuropaeaImportConfigurator fauEuConfig) {
974 
975 		boolean success = true;
976 		
977 		TaxonNameBase<?,?> taxonName = taxonBase.getName();
978 		ZoologicalName zooName = (ZoologicalName)taxonName;
979 		
980 		if (!genusOrUninomial.equals("")) {
981 			zooName.setGenusOrUninomial(emptyToNull(genusOrUninomial));
982 			if (logger.isDebugEnabled()) { 
983 				logger.debug("genusOrUninomial: " + genusOrUninomial); 
984 			}
985 		}
986 		
987 		//if ((!infraGenericEpithet.equals("") && fauEuTaxon.isParenthesis()) || (!infraGenericEpithet.equals("") && fauEuTaxon.)) {
988 		if (fauEuTaxon.getParentRankId() == R_SUBGENUS || fauEuTaxon.getRankId() == R_SUBGENUS ||
989 				fauEuTaxon.getGrandParentRankId() == R_SUBGENUS || fauEuTaxon.getGreatGrandParentRankId() == R_SUBGENUS) {
990 			zooName.setInfraGenericEpithet(emptyToNull(infraGenericEpithet));
991 			if (logger.isDebugEnabled()) { 
992 				logger.debug("infraGenericEpithet: " + infraGenericEpithet); 
993 			}
994 		}
995 		if ((fauEuTaxon.getRankId() == R_SPECIES || fauEuTaxon.getRankId() == R_SUBSPECIES)) {
996 			zooName.setSpecificEpithet(emptyToNull(specificEpithet));
997 			if (logger.isDebugEnabled()) { 
998 				logger.debug("specificEpithet: " + specificEpithet); 
999 			}
1000 		}
1001 		if (fauEuTaxon.getRankId() == R_SUBSPECIES) {
1002 			zooName.setInfraSpecificEpithet(emptyToNull(infraSpecificEpithet));
1003 			if (logger.isDebugEnabled()) { 
1004 				logger.debug("infraSpecificEpithet: " + infraSpecificEpithet); 
1005 			}
1006 		}
1007 		//TODO: use generate NameCache
1008 		//zooName.setNameCache(concatString);
1009 		String result = zooName.getNameCache();
1010 //		zooName.generateTitle();
1011 		//String titleCache = buildNameTitleCache(concatString, useOriginalGenus, fauEuTaxon);
1012 		//zooName.setTitleCache(titleCache);
1013 		//titleCache = buildNameFullTitleCache(concatString, fauEuConfig);
1014 //		zooName.generateFullTitle();
1015 		//zooName.setFullTitleCache(titleCache); // TODO: Add reference, NC status
1016 		
1017 //		ImportHelper.setOriginalSource(taxonName, fauEuConfig.getSourceReference(), 
1018 //				fauEuTaxon.getId(), "TaxonName");
1019 //		taxonBase.setSec(fauEuConfig.getSourceReference());
1020 //		taxonBase.generateTitle();
1021 		//titleCache = buildTaxonTitleCache(concatString, fauEuConfig.getSourceReference());
1022 		//taxonBase.setTitleCache(titleCache);
1023 		
1024 		if (logger.isDebugEnabled()) { 
1025 			logger.debug("Name stored: " + result); 
1026 		}
1027 		return result;
1028 	}
1029 
1030 	/**
1031 	 * Ensures that empty strings are translated to null.
1032 	 * @param genusOrUninomial
1033 	 * @return
1034 	 */
1035 	private String emptyToNull(String text) {
1036 		if (CdmUtils.isEmpty(text)) {
1037 			return null;
1038 		} else {
1039 			return text;
1040 		}
1041 	}
1042 
1043 }