minor feature for taxonX (2.1)
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / taxonx / TaxonXNomenclatureImport.java
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 package eu.etaxonomy.cdm.io.taxonx;
10
11 import java.util.ArrayList;
12 import java.util.HashMap;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
17 import org.apache.log4j.Logger;
18 import org.jdom.Element;
19 import org.jdom.Namespace;
20 import org.springframework.stereotype.Component;
21 import org.springframework.transaction.TransactionStatus;
22
23 import eu.etaxonomy.cdm.api.service.ICommonService;
24 import eu.etaxonomy.cdm.api.service.INameService;
25 import eu.etaxonomy.cdm.api.service.ITaxonService;
26 import eu.etaxonomy.cdm.common.CdmUtils;
27 import eu.etaxonomy.cdm.io.common.CdmIoBase;
28 import eu.etaxonomy.cdm.io.common.ICdmIO;
29 import eu.etaxonomy.cdm.io.common.IImportConfigurator;
30 import eu.etaxonomy.cdm.io.common.MapWrapper;
31 import eu.etaxonomy.cdm.model.agent.AgentBase;
32 import eu.etaxonomy.cdm.model.agent.Person;
33 import eu.etaxonomy.cdm.model.common.CdmBase;
34 import eu.etaxonomy.cdm.model.name.NonViralName;
35 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
36 import eu.etaxonomy.cdm.model.name.TypeDesignationStatus;
37 import eu.etaxonomy.cdm.model.occurrence.Specimen;
38 import eu.etaxonomy.cdm.model.reference.ReferenceBase;
39 import eu.etaxonomy.cdm.model.taxon.Synonym;
40 import eu.etaxonomy.cdm.model.taxon.Taxon;
41 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
42
43
44 /**
45 * @author a.mueller
46 * @created 29.07.2008
47 * @version 1.0
48 */
49 @Component
50 public class TaxonXNomenclatureImport extends CdmIoBase<IImportConfigurator> implements ICdmIO<IImportConfigurator> {
51 private static final Logger logger = Logger.getLogger(TaxonXNomenclatureImport.class);
52
53 @SuppressWarnings("unused")
54 private static int modCount = 10000;
55
56 public TaxonXNomenclatureImport(){
57 super();
58 }
59
60 public boolean doCheck(IImportConfigurator config){
61
62 boolean result = true;
63 logger.warn("Checking for Types not yet implemented");
64 //result &= checkArticlesWithoutJournal(bmiConfig);
65 //result &= checkPartOfJournal(bmiConfig);
66
67 return result;
68 }
69
70 public boolean doInvoke(IImportConfigurator config, Map<String, MapWrapper<? extends CdmBase>> stores){
71 logger.info("start make Nomenclature ...");
72
73 TransactionStatus tx = startTransaction();
74 TaxonXImportConfigurator txConfig = (TaxonXImportConfigurator)config;
75 Element root = txConfig.getSourceRoot();
76 Namespace nsTaxonx = root.getNamespace();
77
78 //for testing only
79 Taxon taxon = getTaxon(txConfig);
80 boolean isChanged = false;
81
82 Element elTaxonBody = root.getChild("taxonxBody", nsTaxonx);
83 Element elTreatment = elTaxonBody.getChild("treatment", nsTaxonx);
84 Element elNomenclature = elTreatment.getChild("nomenclature", nsTaxonx);
85
86 //isChanged |= doCollectionEvent(txConfig, elNomenclature, nsTaxonx, taxon);
87
88 if (taxon != null && taxon.getName() != null && elNomenclature != null){
89 isChanged |= doNomenclaturalType(txConfig, elNomenclature, nsTaxonx, taxon.getName());
90 List<Element> elSynonymyList = new ArrayList<Element>();
91 elSynonymyList.addAll(elNomenclature.getChildren("synonomy", nsTaxonx));
92 elSynonymyList.addAll(elNomenclature.getChildren("synonymy", nsTaxonx)); //wrong spelling in TaxonX-Schema
93 for (Element elSynonymy : elSynonymyList){
94 String synonymName = elSynonymy.getChildTextTrim("name");
95 if (elSynonymy.getChild("type", nsTaxonx) != null || elSynonymy.getChild("type_loc", nsTaxonx) != null){
96 Synonym synonym = getSynonym(txConfig, taxon, synonymName);
97 if (synonym != null){
98 isChanged |= doNomenclaturalType(txConfig, elSynonymy, nsTaxonx, synonym.getName());
99 }
100 }
101 }
102 }
103
104
105 if (isChanged){
106 getTaxonService().saveTaxon(taxon);
107 }
108 commitTransaction(tx);
109 return true;
110 }
111
112 private Synonym getSynonym(TaxonXImportConfigurator config, Taxon taxon, String synName){
113 Synonym result = null;
114 unlazySynonym(config, taxon);
115 Set<Synonym> synList = taxon.getSynonyms();
116 for (Synonym syn : synList){
117 if (syn.getName() != null && ((NonViralName<?>)syn.getName()).getNameCache().equals(synName)){
118 return syn; //only first synonym is returned
119 }
120 }
121 logger.warn("Synonym ("+synName+ ")not found for taxon " + taxon.getTitleCache() + getBracketSourceName(config));
122 return result;
123 }
124
125 private Taxon getTaxon(TaxonXImportConfigurator config){
126 Taxon result;
127 // result = Taxon.NewInstance(BotanicalName.NewInstance(null), null);
128 //ICommonService commonService =config.getCdmAppController().getCommonService();
129 ICommonService commonService = getCommonService();
130 String originalSourceId = config.getOriginalSourceId();
131 String namespace = config.getOriginalSourceTaxonNamespace();
132 result = (Taxon)commonService.getSourcedObjectByIdInSource(Taxon.class, originalSourceId , namespace);
133 if (result == null){
134 logger.warn("Taxon (id: " + originalSourceId + ", namespace: " + namespace + ") could not be found");
135 }
136 return result;
137 }
138
139 /* (non-Javadoc)
140 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
141 */
142 protected boolean isIgnore(IImportConfigurator config){
143 return ! config.isDoFacts();
144 }
145
146 /**
147 *
148 * Reads the collection_event tag, creates the according data and stores it.
149 * TODO under work
150 * @param elNomenclature
151 * @param nsTaxonx
152 * @param taxonBase
153 * @return
154 */
155 private boolean doNomenclaturalType(TaxonXImportConfigurator config, Element elNomenclature, Namespace nsTaxonx, TaxonNameBase taxonName){
156 if (taxonName == null){
157 logger.warn("taxonName is null");
158 return false;
159 }
160 if (elNomenclature == null){
161 logger.warn("elNomenclature is null");
162 return false;
163 }
164
165
166 Element elType = elNomenclature.getChild("type", nsTaxonx);
167 Element elTypeLoc = elNomenclature.getChild("type_loc", nsTaxonx);
168
169 if (elType != null || elTypeLoc != null){
170 ReferenceBase citation = null;
171 String citationMicroReference = null;
172 String originalNameString = null;
173 boolean isNotDesignated = true;
174 boolean addToAllHomotypicNames = true;
175 unlazyTypeDesignation(config, taxonName);
176
177
178 SimpleSpecimen simpleSpecimen = SimpleSpecimen.NewInstance();
179 //elType
180 if (elType != null){
181 doElType(elType, simpleSpecimen, config);
182 }//elType
183
184 //typeLoc
185 HashMap<Specimen, TypeDesignationStatus> typeLocMap = null;
186 if (elTypeLoc != null){
187 typeLocMap = doElTypeLoc(elTypeLoc, simpleSpecimen, taxonName, config);
188 }
189 if (typeLocMap != null && typeLocMap.size() >0){
190 for (Specimen specimen : typeLocMap.keySet()){
191 TypeDesignationStatus status = typeLocMap.get(specimen);
192 taxonName.addSpecimenTypeDesignation(specimen, status, citation, citationMicroReference, originalNameString, isNotDesignated, addToAllHomotypicNames);
193 }
194 }else{ // no type_loc
195 TypeDesignationStatus status = null;
196 taxonName.addSpecimenTypeDesignation(simpleSpecimen.getSpecimen(), status, citation, citationMicroReference, originalNameString, isNotDesignated, addToAllHomotypicNames);
197 }
198 return true;
199 }
200 return false;
201 }
202
203 private boolean doElType(Element elType, SimpleSpecimen simpleSpecimen, TaxonXImportConfigurator config){
204 //type
205 String text = elType.getTextNormalize();
206 if (text.endsWith(";")){
207 text = text + " ";
208 }
209 String[] type = text.split(";");
210 if (type.length != 3 ){
211 if (text.equals("")){
212 logger.info("<nomenclature><type> is empty: " + getBracketSourceName(config));
213 }else{
214 logger.warn("<nomenclature><type> is of unsupported format: " + elType.getTextNormalize() + getBracketSourceName(config));
215 }
216 simpleSpecimen.setTitleCache(elType.getTextNormalize());
217 }else{
218 String strLocality = type[0].trim();
219 if (! "".equals(strLocality)){
220 // simpleSpecimen.setLocality(strLocality);
221 }
222
223 String strCollector = type[1].trim();
224 if (! "".equals(strCollector)){
225 AgentBase collector = Person.NewTitledInstance(strCollector);
226 // simpleSpecimen.setCollector(collector);
227 }
228
229 String strCollectorNumber = type[2].trim();
230 if (! "".equals(strCollectorNumber)){
231 // simpleSpecimen.setCollectorsNumber(strCollectorNumber);
232 }
233
234 String title = CdmUtils.concat(" ", new String[]{strLocality, strCollector, strCollectorNumber});
235 simpleSpecimen.setTitleCache(title);
236 }
237 return true;
238 }
239
240 /**
241 * Reads the typeLoc element split in parts for eacht type (holo, iso,...)
242 * @param elTypeLoc
243 * @param simpleSpecimen
244 * @param taxonName
245 * @param config
246 * @return
247 */
248 private HashMap<Specimen, TypeDesignationStatus> doElTypeLoc(Element elTypeLoc,
249 SimpleSpecimen simpleSpecimen,
250 TaxonNameBase<?,?> taxonName,
251 TaxonXImportConfigurator config){
252
253 HashMap<Specimen, TypeDesignationStatus> result = new HashMap<Specimen, TypeDesignationStatus>();
254
255 String typeLocFullString = elTypeLoc.getTextTrim();
256 typeLocFullString = typeLocFullString.replace("(", "").replace(")", "");
257 String[] typeLocStatusList = typeLocFullString.split(";");
258
259 Specimen originalSpecimen = simpleSpecimen.getSpecimen();
260
261
262 for (String typeLocStatus : typeLocStatusList){
263 typeLocStatus = typeLocStatus.trim();
264 int pos = typeLocStatus.indexOf(" ");
265 if (pos == -1){
266 logger.warn("Unknown format or empty type_loc : '" +typeLocStatus + "'" + getBracketSourceName(config));
267 result.put(originalSpecimen, null);
268 }else{
269 String statusString = typeLocStatus.substring(0,pos);
270 TypeDesignationStatus status = getStatusByStatusString(statusString.trim(), config);
271 //TODO
272 //String[] collectionStrings = typeLocStatus.substring(pos).split(",");
273 String tmpCollString = typeLocStatus.substring(pos).trim();
274 //for(String collectionString : collectionStrings){
275 if (tmpCollString.contains("typ")){
276 logger.warn("Is this really only a collection string? : " + tmpCollString + getBracketSourceName(config));
277 }
278 Specimen specimen;
279 specimen = (Specimen)originalSpecimen.clone();
280 String title = originalSpecimen.getTitleCache();
281 title = title + "(" + tmpCollString + ")";
282 specimen.setTitleCache(title );
283 result.put(specimen, status);
284 //}
285 }
286 }
287
288 return result;
289 }
290
291 /**
292 *
293 * Reads the collection_event tag, creates the according data and stores it.
294 * TODO under work
295 * @param elNomenclature
296 * @param nsTaxonx
297 * @param taxonBase
298 * @return
299 */
300 private boolean doCollectionEvent(TaxonXImportConfigurator config, Element elNomenclature, Namespace nsTaxonx, TaxonBase taxonBase){
301 boolean result = false;
302 if (elNomenclature == null){
303 return false;
304 }
305 Element elCollectionEvent = elNomenclature.getChild("collection_event", nsTaxonx);
306 if (elCollectionEvent == null){
307 return result;
308 }
309 Element elLocality = elCollectionEvent.getChild("locality", nsTaxonx);
310 Element elType = elCollectionEvent.getChild("type", nsTaxonx);
311 Element elTypeLoc = elCollectionEvent.getChild("type_loc", nsTaxonx);
312
313 //locality
314 SimpleSpecimen simpleSpecimen = SimpleSpecimen.NewInstance();
315 String locality = elLocality.getTextNormalize();
316 if (! "".equals(locality)){
317 simpleSpecimen.setLocality(locality);
318 }
319
320 //type
321 String[] type = elType.getTextNormalize().split(" ");
322 if (type.length != 2 ){
323 logger.warn("<collecion_even><type> is of unsupported format: " + elType.getTextNormalize());
324 }else{
325 AgentBase collector = Person.NewTitledInstance(type[0]);
326 simpleSpecimen.setCollector(collector);
327
328 String collectorNumber = type[1];
329 simpleSpecimen.setCollectorsNumber(collectorNumber);
330 }
331
332 //typeLoc
333 String typeLocFullString = elTypeLoc.getTextTrim();
334 typeLocFullString = typeLocFullString.replace("(", "").replace(")", "");
335 String[] typeLocStatusList = typeLocFullString.split(";");
336
337 Specimen originalSpecimen = simpleSpecimen.getSpecimen();
338
339 //TODO special character ?, \86, !
340
341 for (String typeLocStatus : typeLocStatusList){
342 typeLocStatus = typeLocStatus.trim();
343 int pos = typeLocStatus.indexOf(" ");
344 if (pos == -1){
345 logger.warn("Unknown format: " + typeLocStatus);
346 }else{
347 String statusString = typeLocStatus.substring(0,pos);
348 TypeDesignationStatus status = getStatusByStatusString(statusString.trim(), config);
349 String[] collectionStrings = typeLocStatus.substring(pos).split(",");
350 for(String collectionString : collectionStrings){
351 if (taxonBase != null){
352 TaxonNameBase<?, ?> taxonName = taxonBase.getName();
353 if (taxonName != null){
354 ReferenceBase citation = null;
355 String citationMicroReference = null;
356 String originalNameString = null;
357 boolean isNotDesignated = true;
358 boolean addToAllHomotypicNames = true;
359 Specimen specimen = (Specimen)originalSpecimen.clone();
360 unlazyTypeDesignation(config, taxonName);
361 taxonName.addSpecimenTypeDesignation(specimen, status, citation, citationMicroReference, originalNameString, isNotDesignated, addToAllHomotypicNames);
362 result = true;
363 }
364 }
365 }
366 }
367 }
368 return result;
369 }
370
371
372 private static Map<String, TypeDesignationStatus> statusMap;
373 private static void fillTypeStatusMap(){
374 statusMap = new HashMap<String, TypeDesignationStatus>();
375 statusMap.put("holotype", TypeDesignationStatus.HOLOTYPE());
376 statusMap.put("isotype", TypeDesignationStatus.ISOTYPE());
377 statusMap.put("lectotype", TypeDesignationStatus.LECTOTYPE());
378 statusMap.put("syntype", TypeDesignationStatus.SYNTYPE());
379 statusMap.put("isolectotype", TypeDesignationStatus.ISOLECTOTYPE());
380 statusMap.put("type", null);
381 //TODO to be continued
382 }
383
384
385 //TODO move to TypeDesignation class
386 /**
387 * Returns the typeDesignationStatus according to a type designation status string
388 * @param statusString
389 * @return TypeDesignationStatus
390 */
391 private static TypeDesignationStatus getStatusByStatusString(String statusString, TaxonXImportConfigurator config){
392 TypeDesignationStatus result = null;
393 if (statusString == null || "".equals(statusString.trim())){
394 return null;
395 }
396 statusString = statusString.trim().toLowerCase();
397 statusString = statusString.replace("typi", "typus");
398 statusString = statusString.replace("typus", "type");
399 statusString = statusString.replace("types", "type");
400 statusString = statusString.toLowerCase();
401
402 if (statusMap == null){
403 fillTypeStatusMap();
404 }
405 result = statusMap.get(statusString);
406 if (statusString.equals("type")){
407 logger.info("No type designation type" + getBracketSourceName(config));
408 }else if (result == null){
409 logger.warn("Unknown type status string: " + statusString + getBracketSourceName(config));
410 }
411 return result;
412 }
413
414
415 /**
416 * TODO Preliminary to avoid laizy loading errors
417 */
418 private void unlazyTypeDesignation(TaxonXImportConfigurator config, TaxonNameBase taxonNameBase){
419 TransactionStatus txStatus = startTransaction();
420 //INameService taxonNameService = config.getCdmAppController().getNameService();
421 INameService taxonNameService = getNameService();
422
423 taxonNameService.saveTaxonName(taxonNameBase);
424 Set<TaxonNameBase> typifiedNames = taxonNameBase.getHomotypicalGroup().getTypifiedNames();
425 for(TaxonNameBase typifiedName: typifiedNames){
426 typifiedName.getTypeDesignations().size();
427 }
428 //taxonNameService.saveTaxonName(taxonNameBase);
429 commitTransaction(txStatus);
430 }
431
432 /**
433 * TODO Preliminary to avoid laizy loading errors
434 */
435 private void unlazySynonym(IImportConfigurator config, Taxon taxon){
436 TransactionStatus txStatus = startTransaction();
437 ITaxonService taxonService = getTaxonService();
438 taxonService.saveTaxon(taxon);
439 Set<Synonym> synonyms = taxon.getSynonyms();
440 logger.debug(synonyms.size());
441 //taxonService.saveTaxon(taxon);
442 commitTransaction(txStatus);
443 }
444
445 private static String getBracketSourceName(TaxonXImportConfigurator config){
446 return "(" + config.getSourceNameString() + ")";
447 }
448
449
450 }