869b12f4305e32340bd1ace440f15540739a433d
[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.Agent;
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 logger.warn("<nomenclature><type> is of unsupported format: " + elType.getTextNormalize() + getBracketSourceName(config));
212 simpleSpecimen.setTitleCache(elType.getTextNormalize());
213 }else{
214 String strLocality = type[0].trim();
215 if (! "".equals(strLocality)){
216 // simpleSpecimen.setLocality(strLocality);
217 }
218
219 String strCollector = type[1].trim();
220 if (! "".equals(strCollector)){
221 Agent collector = Person.NewTitledInstance(strCollector);
222 // simpleSpecimen.setCollector(collector);
223 }
224
225 String strCollectorNumber = type[2].trim();
226 if (! "".equals(strCollectorNumber)){
227 // simpleSpecimen.setCollectorsNumber(strCollectorNumber);
228 }
229
230 String title = CdmUtils.concat(" ", new String[]{strLocality, strCollector, strCollectorNumber});
231 simpleSpecimen.setTitleCache(title);
232 }
233 return true;
234 }
235
236 /**
237 * Reads the typeLoc element split in parts for eacht type (holo, iso,...)
238 * @param elTypeLoc
239 * @param simpleSpecimen
240 * @param taxonName
241 * @param config
242 * @return
243 */
244 private HashMap<Specimen, TypeDesignationStatus> doElTypeLoc(Element elTypeLoc,
245 SimpleSpecimen simpleSpecimen,
246 TaxonNameBase<?,?> taxonName,
247 TaxonXImportConfigurator config){
248
249 HashMap<Specimen, TypeDesignationStatus> result = new HashMap<Specimen, TypeDesignationStatus>();
250
251 String typeLocFullString = elTypeLoc.getTextTrim();
252 typeLocFullString = typeLocFullString.replace("(", "").replace(")", "");
253 String[] typeLocStatusList = typeLocFullString.split(";");
254
255 Specimen originalSpecimen = simpleSpecimen.getSpecimen();
256
257
258 for (String typeLocStatus : typeLocStatusList){
259 typeLocStatus = typeLocStatus.trim();
260 int pos = typeLocStatus.indexOf(" ");
261 if (pos == -1){
262 logger.warn("Unknown format for type_loc : " + typeLocStatus + getBracketSourceName(config));
263 result.put(originalSpecimen, null);
264 }else{
265 String statusString = typeLocStatus.substring(0,pos);
266 TypeDesignationStatus status = getStatusByStatusString(statusString.trim());
267 //TODO
268 //String[] collectionStrings = typeLocStatus.substring(pos).split(",");
269 String tmpCollString = typeLocStatus.substring(pos).trim();
270 //for(String collectionString : collectionStrings){
271 if (tmpCollString.contains("typ")){
272 logger.warn("Is this really only a collection string? : " + tmpCollString + getBracketSourceName(config));
273 }
274 Specimen specimen;
275 specimen = (Specimen)originalSpecimen.clone();
276 String title = originalSpecimen.getTitleCache();
277 title = title + "(" + tmpCollString + ")";
278 specimen.setTitleCache(title );
279 result.put(specimen, status);
280 //}
281 }
282 }
283
284 return result;
285 }
286
287 /**
288 *
289 * Reads the collection_event tag, creates the according data and stores it.
290 * TODO under work
291 * @param elNomenclature
292 * @param nsTaxonx
293 * @param taxonBase
294 * @return
295 */
296 private boolean doCollectionEvent(TaxonXImportConfigurator config, Element elNomenclature, Namespace nsTaxonx, TaxonBase taxonBase){
297 boolean result = false;
298 if (elNomenclature == null){
299 return false;
300 }
301 Element elCollectionEvent = elNomenclature.getChild("collection_event", nsTaxonx);
302 if (elCollectionEvent == null){
303 return result;
304 }
305 Element elLocality = elCollectionEvent.getChild("locality", nsTaxonx);
306 Element elType = elCollectionEvent.getChild("type", nsTaxonx);
307 Element elTypeLoc = elCollectionEvent.getChild("type_loc", nsTaxonx);
308
309 //locality
310 SimpleSpecimen simpleSpecimen = SimpleSpecimen.NewInstance();
311 String locality = elLocality.getTextNormalize();
312 if (! "".equals(locality)){
313 simpleSpecimen.setLocality(locality);
314 }
315
316 //type
317 String[] type = elType.getTextNormalize().split(" ");
318 if (type.length != 2 ){
319 logger.warn("<collecion_even><type> is of unsupported format: " + elType.getTextNormalize());
320 }else{
321 Agent collector = Person.NewTitledInstance(type[0]);
322 simpleSpecimen.setCollector(collector);
323
324 String collectorNumber = type[1];
325 simpleSpecimen.setCollectorsNumber(collectorNumber);
326 }
327
328 //typeLoc
329 String typeLocFullString = elTypeLoc.getTextTrim();
330 typeLocFullString = typeLocFullString.replace("(", "").replace(")", "");
331 String[] typeLocStatusList = typeLocFullString.split(";");
332
333 Specimen originalSpecimen = simpleSpecimen.getSpecimen();
334
335 //TODO special character ?, \86, !
336
337 for (String typeLocStatus : typeLocStatusList){
338 typeLocStatus = typeLocStatus.trim();
339 int pos = typeLocStatus.indexOf(" ");
340 if (pos == -1){
341 logger.warn("Unknown format: " + typeLocStatus);
342 }else{
343 String statusString = typeLocStatus.substring(0,pos);
344 TypeDesignationStatus status = getStatusByStatusString(statusString.trim());
345 String[] collectionStrings = typeLocStatus.substring(pos).split(",");
346 for(String collectionString : collectionStrings){
347 if (taxonBase != null){
348 TaxonNameBase<?, ?> taxonName = taxonBase.getName();
349 if (taxonName != null){
350 ReferenceBase citation = null;
351 String citationMicroReference = null;
352 String originalNameString = null;
353 boolean isNotDesignated = true;
354 boolean addToAllHomotypicNames = true;
355 Specimen specimen = (Specimen)originalSpecimen.clone();
356 unlazyTypeDesignation(config, taxonName);
357 taxonName.addSpecimenTypeDesignation(specimen, status, citation, citationMicroReference, originalNameString, isNotDesignated, addToAllHomotypicNames);
358 result = true;
359 }
360 }
361 }
362 }
363 }
364 return result;
365 }
366
367
368 private static Map<String, TypeDesignationStatus> statusMap;
369 private static void fillTypeStatusMap(){
370 statusMap = new HashMap<String, TypeDesignationStatus>();
371 statusMap.put("holotype", TypeDesignationStatus.HOLOTYPE());
372 statusMap.put("isotype", TypeDesignationStatus.ISOTYPE());
373 statusMap.put("lectotype", TypeDesignationStatus.LECTOTYPE());
374 statusMap.put("syntype", TypeDesignationStatus.SYNTYPE());
375 statusMap.put("isolectotype", TypeDesignationStatus.ISOLECTOTYPE());
376 statusMap.put("type", null);
377 //TODO to be continued
378 }
379
380
381 //TODO move to TypeDesignation class
382 /**
383 * Returns the typeDesignationStatus according to a type designation status string
384 * @param statusString
385 * @return TypeDesignationStatus
386 */
387 private static TypeDesignationStatus getStatusByStatusString(String statusString){
388 TypeDesignationStatus result = null;
389 if (statusString == null || "".equals(statusString.trim())){
390 return null;
391 }
392 statusString = statusString.trim().toLowerCase();
393 statusString = statusString.replace("typi", "typus");
394 statusString = statusString.replace("typus", "type");
395 statusString = statusString.replace("types", "type");
396 statusString = statusString.toLowerCase();
397
398 if (statusMap == null){
399 fillTypeStatusMap();
400 }
401 result = statusMap.get(statusString);
402 if (statusString.equals("type")){
403 logger.info("No type designation type");
404 }else if (result == null){
405 logger.warn("Unknown type status string: " + statusString);
406 }
407 return result;
408 }
409
410
411 /**
412 * TODO Preliminary to avoid laizy loading errors
413 */
414 private void unlazyTypeDesignation(TaxonXImportConfigurator config, TaxonNameBase taxonNameBase){
415 TransactionStatus txStatus = startTransaction();
416 //INameService taxonNameService = config.getCdmAppController().getNameService();
417 INameService taxonNameService = getNameService();
418
419 taxonNameService.saveTaxonName(taxonNameBase);
420 Set<TaxonNameBase> typifiedNames = taxonNameBase.getHomotypicalGroup().getTypifiedNames();
421 for(TaxonNameBase typifiedName: typifiedNames){
422 typifiedName.getTypeDesignations().size();
423 }
424 //taxonNameService.saveTaxonName(taxonNameBase);
425 commitTransaction(txStatus);
426 }
427
428 /**
429 * TODO Preliminary to avoid laizy loading errors
430 */
431 private void unlazySynonym(IImportConfigurator config, Taxon taxon){
432 TransactionStatus txStatus = startTransaction();
433 ITaxonService taxonService = getTaxonService();
434 taxonService.saveTaxon(taxon);
435 Set<Synonym> synonyms = taxon.getSynonyms();
436 logger.debug(synonyms.size());
437 //taxonService.saveTaxon(taxon);
438 commitTransaction(txStatus);
439 }
440
441 private String getBracketSourceName(TaxonXImportConfigurator config){
442 return "(" + config.getSourceNameString() + ")";
443 }
444
445
446 }