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.excel.taxa;
11  
12  import java.util.HashMap;
13  import java.util.Set;
14  
15  import org.apache.log4j.Logger;
16  import org.springframework.stereotype.Component;
17  
18  import eu.etaxonomy.cdm.common.CdmUtils;
19  import eu.etaxonomy.cdm.model.common.Language;
20  import eu.etaxonomy.cdm.model.description.CommonTaxonName;
21  import eu.etaxonomy.cdm.model.description.TaxonDescription;
22  import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
23  import eu.etaxonomy.cdm.model.name.NonViralName;
24  import eu.etaxonomy.cdm.model.name.Rank;
25  import eu.etaxonomy.cdm.model.name.TaxonNameBase;
26  import eu.etaxonomy.cdm.model.reference.ReferenceBase;
27  import eu.etaxonomy.cdm.model.taxon.Synonym;
28  import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
29  import eu.etaxonomy.cdm.model.taxon.Taxon;
30  import eu.etaxonomy.cdm.model.taxon.TaxonBase;
31  import eu.etaxonomy.cdm.model.taxon.TaxonomicTree;
32  import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
33  import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
34  
35  /**
36   * @author a.babadshanjan
37   * @created 08.01.2009
38   * @version 1.0
39   */
40  
41  @Component
42  public class NormalExplicitImport extends TaxonExcelImporterBase {
43  	private static final Logger logger = Logger.getLogger(NormalExplicitImport.class);
44  	
45  	@Override
46  	protected boolean isIgnore(TaxonExcelImportState state) {
47  		return false;
48  	}
49  	
50  	private int floatString2IntValue(String value) {
51  		
52  		int intValue = 0;
53  		try {
54  			Float fobj = new Float(Float.parseFloat(value));
55  			intValue = fobj.intValue();
56  			if (logger.isDebugEnabled()) { logger.debug("Value formatted: " + intValue); }
57  		} catch (NumberFormatException ex) {
58  			logger.error(value + " is not an integer");
59  		}
60  		return intValue;
61  	}
62  	
63  	
64  	
65  	/* (non-Javadoc)
66  	 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
67  	 */
68  	@Override
69  	protected boolean doCheck(TaxonExcelImportState state) {
70  		logger.warn("DoCheck not yet implemented for NormalExplicitImport");
71  		return true;
72  	}
73  
74  	@Override
75      protected boolean analyzeRecord(HashMap<String, String> record, TaxonExcelImportState state) {
76  		
77  		boolean success = true;
78      	Set<String> keys = record.keySet();
79      	
80      	NormalExplicitRow normalExplicitRow = new NormalExplicitRow();
81      	state.setTaxonLight(normalExplicitRow);
82      	
83      	for (String key: keys) {
84      		
85      		key = CdmUtils.removeDuplicateWhitespace(key.trim()).toString();
86      		
87      		String value = (String) record.get(key);
88      		if (!CdmUtils.isEmpty(value)) {
89      			if (logger.isDebugEnabled()) { logger.debug(key + ": " + value); }
90          		value = CdmUtils.removeDuplicateWhitespace(value.trim()).toString();
91      		}
92      		
93      		if (key.equalsIgnoreCase(ID_COLUMN)) {
94      			int ivalue = floatString2IntValue(value);
95      			normalExplicitRow.setId(ivalue);
96      			
97  			} else if(key.equalsIgnoreCase(PARENT_ID_COLUMN)) {
98  				int ivalue = floatString2IntValue(value);
99  				normalExplicitRow.setParentId(ivalue);
100 				
101 			} else if(key.equalsIgnoreCase(RANK_COLUMN)) {
102 				normalExplicitRow.setRank(value);
103     			
104 			} else if(key.equalsIgnoreCase(SCIENTIFIC_NAME_COLUMN)) {
105 				normalExplicitRow.setScientificName(value);
106     			
107 			} else if(key.equalsIgnoreCase(AUTHOR_COLUMN)) {
108 				normalExplicitRow.setAuthor(value);
109    			
110 			} else if(key.equalsIgnoreCase(NAME_STATUS_COLUMN)) {
111 				normalExplicitRow.setNameStatus(value);
112     			
113 			} else if(key.equalsIgnoreCase(VERNACULAR_NAME_COLUMN)) {
114 				normalExplicitRow.setCommonName(value);
115     			
116 			} else if(key.equalsIgnoreCase(LANGUAGE_COLUMN)) {
117 				normalExplicitRow.setLanguage(value);
118     			
119 			} else {
120 				success = false;
121 				logger.error("Unexpected column header " + key);
122 			}
123     	}
124     	return success;
125     }
126 	
127 	
128 	/** 
129 	 *  Stores taxa records in DB
130 	 */
131 	@Override
132     protected boolean firstPass(TaxonExcelImportState state) {
133 		boolean success = true;
134 		Rank rank = null;
135 		
136 		String rankStr = state.getTaxonLight().getRank();
137 		String taxonNameStr = state.getTaxonLight().getScientificName();
138 		String authorStr = state.getTaxonLight().getAuthor();
139 		String nameStatus = state.getTaxonLight().getNameStatus();
140 		Integer id = state.getTaxonLight().getId();
141 			
142 		if (CdmUtils.isNotEmpty(taxonNameStr)) {
143 
144 			// Determine the rank
145 			try {
146 				rank = Rank.getRankByName(rankStr);
147 			} catch (UnknownCdmTypeException ex) {
148 				success = false;
149 				logger.error(rankStr + " is not a valid rank.");
150 			}
151 			
152             // Create the taxon name object depending on the setting of the nomenclatural code 
153 			// in the configurator (botanical code, zoological code, etc.) 
154 			NomenclaturalCode nc = getConfigurator().getNomenclaturalCode();
155 			NonViralName taxonNameBase;
156 			if (nc == NomenclaturalCode.ICVCN){
157 				logger.warn("ICVCN not yet supported");
158 				return false;
159 			}else{
160 				taxonNameBase =(NonViralName) nc.getNewTaxonNameInstance(rank);
161 				//NonViralName nonViralName = (NonViralName)taxonNameBase;
162 				//TODO parse name
163 				NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
164 				taxonNameBase = parser.parseFullName(taxonNameStr, nc, rank);
165 				
166 				taxonNameBase.setNameCache(taxonNameStr);
167 				
168 				// Create the author
169 				if (CdmUtils.isNotEmpty(authorStr)) {
170 					//TODO parse authors
171 					//if (state.getAuthor(authorStr)!= null) {
172 					taxonNameBase.setAuthorshipCache(authorStr);
173 //					} else {
174 //						state.putAuthor(authorStr, null);
175 //						Person author = Person.NewTitledInstance(authorStr);
176 //						nonViralName.setCombinationAuthorTeam(author);
177 //					}
178 				}
179 			}
180 			
181 			//Create the taxon
182 			ReferenceBase sec = state.getConfig().getSourceReference();
183 			TaxonBase taxonBase;
184 			// Create the nomenclatural status
185 			if (CdmUtils.isEmpty(nameStatus) || nameStatus.equalsIgnoreCase("valid")){
186 				taxonBase = Taxon.NewInstance(taxonNameBase, sec);
187 			}else{
188 				taxonBase = Synonym.NewInstance(taxonNameBase, sec);
189 			}
190 			state.putTaxon(id, taxonBase);
191 			getTaxonService().save(taxonBase);
192 		}
193 		return success;
194     }
195 
196 
197 	/** 
198 	 *  Stores parent-child, synonym and common name relationships
199 	 */
200 	@Override
201     protected boolean secondPass(TaxonExcelImportState state) {
202 		boolean success = true;
203 		String taxonNameStr = state.getTaxonLight().getScientificName();
204 		String nameStatus = state.getTaxonLight().getNameStatus();
205 		String commonNameStr = state.getTaxonLight().getCommonName();
206 		Integer parentId = state.getTaxonLight().getParentId();
207 		Integer childId = state.getTaxonLight().getId();
208 		
209 		Taxon parentTaxon = (Taxon)state.getTaxonBase(parentId);
210 		Taxon taxon = (Taxon)state.getTaxonBase(childId);
211 		if (CdmUtils.isNotEmpty(taxonNameStr)) {
212 			if (nameStatus != null && nameStatus.equalsIgnoreCase("invalid")){
213 				//add synonym relationship
214 				Synonym synonym = (Synonym)state.getTaxonBase(childId);
215 				parentTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
216 			}else if (nameStatus == null || nameStatus.equalsIgnoreCase("valid")){
217 				// Add the parent relationship
218 				if (state.getTaxonLight().getParentId() != 0) {
219 					if (parentTaxon != null) {
220 						//Taxon taxon = (Taxon)state.getTaxonBase(childId);
221 						
222 						ReferenceBase citation = state.getConfig().getSourceReference();
223 						String microCitation = null;
224 						Taxon childTaxon = taxon;
225 						success &= makeParent(state, parentTaxon, childTaxon, citation, microCitation);
226 						getTaxonService().save(parentTaxon);
227 					} else {
228 						logger.warn("Taxonomic parent not found for " + taxonNameStr);
229 						success = false;
230 					}
231 				}else{
232 					//do nothing (parent == 0) no parent exists
233 				}
234 			}
235 		} 
236 		if (CdmUtils.isNotEmpty(commonNameStr))
237 		{			// add common name to taxon
238 			
239 			Language language = getTermService().getLanguageByIso(state.getTaxonLight().getLanguage());
240 			if (language == null && CdmUtils.isNotEmpty(state.getTaxonLight().getLanguage())  ){
241 				String error ="Language is null but shouldn't"; 
242 				logger.error(error);
243 				throw new IllegalArgumentException(error);
244 			}
245 			CommonTaxonName commonTaxonName = CommonTaxonName.NewInstance(commonNameStr, language);
246 			try {
247 				TaxonDescription taxonDescription = getDescription(taxon);
248 				taxonDescription.addElement(commonTaxonName);
249 				logger.info("Common name " + commonNameStr + " added to " + taxon.getTitleCache());
250 			} catch (ClassCastException ex) {
251 				logger.error(taxonNameStr + " is not a taxon instance.");
252 			}
253 		}
254 		return success;
255 	}
256 	
257 	/**
258 	 * @param taxon
259 	 * @return
260 	 */
261 	//TODO implementation must be improved when matching of taxa with existing taxa is implemented
262 	//=> the assumption that the only description is the description added by this import
263 	//is wrong then
264 	private TaxonDescription getDescription(Taxon taxon) {
265 		Set<TaxonDescription> descriptions = taxon.getDescriptions();
266 		if (descriptions.size()>1){
267 			throw new IllegalStateException("Implementation does not yet support taxa with multiple descriptions");
268 		}else if (descriptions.size()==1){
269 			return descriptions.iterator().next();
270 		}else{
271 			return TaxonDescription.NewInstance(taxon);
272 		}
273 	}
274 
275 	private boolean makeParent(TaxonExcelImportState state, Taxon parentTaxon, Taxon childTaxon, ReferenceBase citation, String microCitation){
276 		boolean success = true;
277 		ReferenceBase sec = parentTaxon.getSec();
278 		TaxonomicTree tree = state.getTree(sec);
279 		if (tree == null){
280 			tree = makeTree(state, sec);
281 		}
282 		success &=  (null !=  tree.addParentChild(parentTaxon, childTaxon, citation, microCitation));
283 		return success;
284 	}
285 	
286 
287 	
288 }