Refactored string constants
[cdmlib-apps.git] / app-import / src / main / java / eu / etaxonomy / cdm / io / redlist / bfnXml / in / BfnXmlImportTaxonName.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
10 package eu.etaxonomy.cdm.io.redlist.bfnXml.in;
11
12 import java.util.ArrayList;
13 import java.util.Collection;
14 import java.util.LinkedHashMap;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.UUID;
18
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.jdom.Element;
22 import org.jdom.Namespace;
23 import org.springframework.stereotype.Component;
24 import org.springframework.transaction.TransactionStatus;
25
26 import eu.etaxonomy.cdm.api.service.IClassificationService;
27 import eu.etaxonomy.cdm.api.service.ITaxonService;
28 import eu.etaxonomy.cdm.common.ResultWrapper;
29 import eu.etaxonomy.cdm.common.XmlHelp;
30 import eu.etaxonomy.cdm.io.redlist.bfnXml.BfnXmlConstants;
31 import eu.etaxonomy.cdm.model.common.CdmBase;
32 import eu.etaxonomy.cdm.model.common.DefinedTermBase;
33 import eu.etaxonomy.cdm.model.common.Language;
34 import eu.etaxonomy.cdm.model.common.TermVocabulary;
35 import eu.etaxonomy.cdm.model.description.CategoricalData;
36 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
37 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
38 import eu.etaxonomy.cdm.model.description.Distribution;
39 import eu.etaxonomy.cdm.model.description.Feature;
40 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
41 import eu.etaxonomy.cdm.model.description.State;
42 import eu.etaxonomy.cdm.model.description.TaxonDescription;
43 import eu.etaxonomy.cdm.model.description.TextData;
44 import eu.etaxonomy.cdm.model.location.NamedArea;
45 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
46 import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
47 import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
48 import eu.etaxonomy.cdm.model.name.NonViralName;
49 import eu.etaxonomy.cdm.model.name.Rank;
50 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
51 import eu.etaxonomy.cdm.model.reference.Reference;
52 import eu.etaxonomy.cdm.model.taxon.Classification;
53 import eu.etaxonomy.cdm.model.taxon.Synonym;
54 import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
55 import eu.etaxonomy.cdm.model.taxon.Taxon;
56 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
57 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
58 import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
59 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
60 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
61 import eu.etaxonomy.cdm.strategy.parser.ParserProblem;
62 /**
63 *
64 * @author a.oppermann
65 * @date 04.07.2013
66 *
67 */
68 //@Component("bfnXmlTaxonNameIO")
69 @Component
70 public class BfnXmlImportTaxonName extends BfnXmlImportBase {
71
72 private static final Logger logger = Logger.getLogger(BfnXmlImportTaxonName.class);
73
74 private static NomenclaturalCode nomenclaturalCode = null;
75 private static int parsingProblemCounter = 0;
76 private Map<Integer, Taxon> firstList;
77 private Map<Integer, Taxon> secondList;
78
79
80 public BfnXmlImportTaxonName(){
81 super();
82 }
83
84
85 @Override
86 @SuppressWarnings({"rawtypes" })
87 public void doInvoke(BfnXmlImportState state){
88 ITaxonService taxonService = getTaxonService();
89
90 BfnXmlImportConfigurator config = state.getConfig();
91 nomenclaturalCode = config.getNomenclaturalCode();
92 Element elDataSet = getDataSetElement(config);
93 //TODO set Namespace
94 Namespace bfnNamespace = config.getBfnXmlNamespace();
95
96 List<?> contentXML = elDataSet.getContent();
97 Element currentElement = null;
98 for(Object object:contentXML){
99
100 if(object instanceof Element){
101 currentElement = (Element)object;
102 //import taxon lists
103 if(currentElement.getName().equalsIgnoreCase(BfnXmlConstants.EL_ROTELISTEDATEN)){
104 TransactionStatus tx = startTransaction();
105 Map<UUID, TaxonBase> savedTaxonMap = extractTaxonNames(state, taxonService, config, currentElement, bfnNamespace);
106 createOrUpdateClassification(config, taxonService, savedTaxonMap, currentElement, state);
107 commitTransaction(tx);
108 }//import concept relations of taxon lists
109 if(config.isHasSecondList()){
110 if(currentElement.getName().equalsIgnoreCase(BfnXmlConstants.EL_KONZEPTBEZIEHUNGEN)){
111 TransactionStatus tx = startTransaction();
112 extractTaxonConceptRelationShips(bfnNamespace,currentElement);
113 commitTransaction(tx);
114 }
115 }
116 }
117 }
118 return;
119 }
120
121 /**
122 * This method will parse the XML concept relationships and tries to map them into cdm relationship types.
123 *
124 * @param bfnNamespace
125 * @param currentElement
126 */
127 private void extractTaxonConceptRelationShips(Namespace bfnNamespace, Element currentElement) {
128 String childName;
129 String bfnElementName = BfnXmlConstants.EL_KONZEPTBEZIEHUNG;
130 ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
131 List<Element> elConceptList = currentElement.getChildren(bfnElementName, bfnNamespace);
132 List<TaxonBase> updatedTaxonList = new ArrayList<TaxonBase>();
133 for(Element element:elConceptList){
134
135 childName = "TAXONYM1";
136 Element elTaxon1 = XmlHelp.getSingleChildElement(success, element, childName, bfnNamespace, false);
137 String taxNr1 = elTaxon1.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
138 int int1 = Integer.parseInt(taxNr1);
139 Taxon taxon1 = firstList.get(int1);
140 TaxonBase<?> taxonBase1 = getTaxonService().load(taxon1.getUuid());
141 taxon1 = (Taxon)taxonBase1;
142
143 childName = "TAXONYM2";
144 Element elTaxon2 = XmlHelp.getSingleChildElement(success, element, childName, bfnNamespace, false);
145 String taxNr2 = elTaxon2.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
146 int int2 = Integer.parseInt(taxNr2);
147 Taxon taxon2 = secondList.get(int2);
148 TaxonBase<?> taxonBase2 = getTaxonService().load(taxon2.getUuid());
149 taxon2 = (Taxon) taxonBase2;
150
151 childName = "STATUS";
152 Element elConceptStatus = XmlHelp.getSingleChildElement(success, element, childName, bfnNamespace, false);
153 String conceptStatusValue = elConceptStatus.getValue();
154 conceptStatusValue = conceptStatusValue.replaceAll("\u00A0", "").trim();
155 TaxonRelationshipType taxonRelationType = null;
156 /**
157 * This if case only exists because it was decided not to have a included_in relationship type.
158 */
159 if(conceptStatusValue.equalsIgnoreCase("<")){
160 taxon2.addTaxonRelation(taxon1, TaxonRelationshipType.INCLUDES(), null, null);
161 }else{
162 try {
163 taxonRelationType = BfnXmlTransformer.concept2TaxonRelation(conceptStatusValue);
164 } catch (UnknownCdmTypeException e) {
165 e.printStackTrace();
166 }
167 taxon1.addTaxonRelation(taxon2, taxonRelationType , null, null);
168 }
169 if(taxonRelationType != null && taxonRelationType.equals(TaxonRelationshipType.ALL_RELATIONSHIPS())){
170 List<TaxonRelationship> relationsFromThisTaxon = (List<TaxonRelationship>) taxon1.getRelationsFromThisTaxon();
171 TaxonRelationship taxonRelationship = relationsFromThisTaxon.get(0);
172 taxonRelationship.setDoubtful(true);
173 }
174 updatedTaxonList.add(taxon2);
175 updatedTaxonList.add(taxon1);
176 }
177 getTaxonService().saveOrUpdate(updatedTaxonList);
178 logger.info("taxon relationships imported...");
179 }
180
181 /**
182 * This method stores the current imported maps in global variables to make
183 * them later available for matching the taxon relationships between these
184 * imported lists.
185 *
186 * @param config
187 * @param taxonMap
188 */
189 private void prepareListforConceptImport(BfnXmlImportConfigurator config,Map<Integer, Taxon> taxonMap) {
190 if(config.isFillSecondList()){
191 secondList = taxonMap;
192 }else{
193 firstList = taxonMap;
194 }
195 }
196
197 /**
198 *
199 * @param state
200 * @param taxonService
201 * @param config
202 * @param elDataSet
203 * @param bfnNamespace
204 * @return
205 */
206 private Map<UUID, TaxonBase> extractTaxonNames(BfnXmlImportState state,
207 ITaxonService taxonService, BfnXmlImportConfigurator config,
208 Element elDataSet, Namespace bfnNamespace) {
209 logger.info("start make TaxonNames...");
210 Map<Integer, Taxon> taxonMap = new LinkedHashMap<Integer, Taxon>();
211 ResultWrapper<Boolean> success = ResultWrapper.NewInstance(true);
212 String childName;
213 boolean obligatory;
214 String idNamespace = "TaxonName";
215
216 childName = BfnXmlConstants.EL_TAXONYME;
217 obligatory = false;
218 Element elTaxonNames = XmlHelp.getSingleChildElement(success, elDataSet, childName, bfnNamespace, obligatory);
219
220 String bfnElementName = BfnXmlConstants.EL_TAXONYM;
221 List<Element> elTaxonList = elTaxonNames.getChildren(bfnElementName, bfnNamespace);
222
223 //for each taxonName
224 for (Element elTaxon : elTaxonList){
225 //create Taxon
226 String taxonId = elTaxon.getAttributeValue(BfnXmlConstants.ATT_TAXNR);
227 childName = BfnXmlConstants.EL_WISSNAME;
228 Element elWissName = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
229 String childElementName = BfnXmlConstants.EL_NANTEIL;
230 Taxon taxon = createOrUpdateTaxon(success, idNamespace, config, bfnNamespace, elWissName, childElementName, state);
231
232 //for each synonym
233 childName = "SYNONYME";
234 Element elSynonyms = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
235 if(elSynonyms != null){
236 childElementName = "SYNONYM";
237 createOrUpdateSynonym(taxon, success, obligatory, bfnNamespace, childElementName,elSynonyms, taxonId, state);
238 }
239 //for vernacular name
240 childName = BfnXmlConstants.EL_DEUTSCHENAMEN;
241 Element elVernacularName = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
242 if(elVernacularName != null){
243 childElementName = BfnXmlConstants.EL_DNAME;
244 createOrUpdateVernacularName(taxon, bfnNamespace, childElementName, elVernacularName, state);
245 }
246 //for each information concerning the taxon element
247 //TODO Information block
248 if(config.isDoInformationImport()){
249 childName = BfnXmlConstants.EL_INFORMATIONEN;
250 Element elInformations = XmlHelp.getSingleChildElement(success, elTaxon, childName, bfnNamespace, obligatory);
251 if(elInformations != null){
252 childElementName = BfnXmlConstants.EL_BEZUGSRAUM;
253 createOrUpdateInformation(taxon, bfnNamespace, childElementName,elInformations, state);
254 }
255 }
256 taxonMap.put(Integer.parseInt(taxonId), taxon);
257 }
258
259 //Quick'n'dirty to set concept relationships between two imported list
260 prepareListforConceptImport(config, taxonMap);
261
262 Map<UUID, TaxonBase> savedTaxonMap = taxonService.saveOrUpdate((Collection)taxonMap.values());
263 //FIXME: after first list don't import metadata yet
264 //TODO: import information for second taxon list.
265 config.setDoInformationImport(false);
266 logger.info("end makeTaxonNames ...");
267 if (!success.getValue()){
268 state.setUnsuccessfull();
269 }
270 return savedTaxonMap;
271 }
272
273
274
275
276 /**
277 * This will put the prior imported list into a classification
278 *
279 * @param config
280 * @param taxonService
281 * @param config
282 * @param savedTaxonMap
283 * @param currentElement
284 * @param state
285 * @return
286 */
287 @SuppressWarnings("rawtypes")
288 private boolean createOrUpdateClassification(BfnXmlImportConfigurator config, ITaxonService taxonService, Map<UUID, TaxonBase> savedTaxonMap, Element currentElement, BfnXmlImportState state) {
289 boolean isNewClassification = true;
290 String classificationName = state.getFirstClassificationName();
291 if(config.isFillSecondList()){
292 classificationName = state.getSecondClassificationName();
293 }
294 // if(classificationName == null){
295 // classificationName = config.getClassificationName();
296 // }
297 //TODO make classification name dynamically depending on its value in the XML.
298 Classification classification = Classification.NewInstance(classificationName+" "+currentElement.getAttributeValue("inhalt"), state.getCompleteSourceRef());
299 //TODO do we really want toString() or titleCache here?
300 String microRef = state.getCurrentMicroRef() == null ? null : state.getCurrentMicroRef().toString();
301 classification.addImportSource(Integer.toString(classification.getId()), classification.getTitleCache(), state.getCompleteSourceRef(), microRef);
302 // List<Classification> classificationList = getClassificationService().list(Classification.class, null, null, null, VOC_CLASSIFICATION_INIT_STRATEGY);
303 // for(Classification c : classificationList){
304 // if(c.getTitleCache().equalsIgnoreCase(classification.getTitleCache())){
305 // classification = c;
306 // isNewClassification = false;
307 // }
308 // }
309
310 // ArrayList<TaxonBase> taxonBaseList = (ArrayList<TaxonBase>) taxonService.list(TaxonBase.class, null, null, null, VOC_CLASSIFICATION_INIT_STRATEGY);
311 for(TaxonBase tb:savedTaxonMap.values()){
312 if(tb instanceof Taxon){
313 TaxonBase tbase = CdmBase.deproxy(tb, TaxonBase.class);
314 Taxon taxon = (Taxon)tbase;
315 taxon = CdmBase.deproxy(taxon, Taxon.class);
316 classification.addChildTaxon(taxon, null, null);
317 }
318 }
319 IClassificationService classificationService = getClassificationService();
320 classificationService.saveOrUpdate(classification);
321 //set boolean for reference and internal mapping of concept relations
322 if(config.isHasSecondList()){
323 config.setFillSecondList(true);
324 }
325 return isNewClassification;
326 }
327
328
329
330 /**
331 * Matches the XML attributes against CDM entities.<BR>
332 * Imports Scientific Name, Rank, etc. and creates a taxon.<br>
333 * <b>Existing taxon names won't be matched yet</b>
334 *
335 * @param success
336 * @param idNamespace
337 * @param config
338 * @param bfnNamespace
339 * @param elTaxonName
340 * @param childElementName
341 * @param state
342 * @return
343 */
344
345 @SuppressWarnings({ "unchecked" })
346 private Taxon createOrUpdateTaxon(
347 ResultWrapper<Boolean> success, String idNamespace,
348 BfnXmlImportConfigurator config, Namespace bfnNamespace,
349 Element elTaxonName, String childElementName, BfnXmlImportState state) {
350
351 List<Element> elWissNameList = elTaxonName.getChildren(childElementName, bfnNamespace);
352 Rank rank = null;
353 String strAuthor = null;
354 String strSupplement = null;
355 Taxon taxon = null;
356 String uniqueID = null;
357 String uriNameSpace = null;
358 // Long uniqueID = null;
359 for(Element elWissName:elWissNameList){
360
361 if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Eindeutiger Code")){
362 uriNameSpace = elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH);
363 String textNormalize = elWissName.getTextNormalize();
364 if(StringUtils.isBlank(textNormalize)){
365 uniqueID = "";
366 }else{
367 uniqueID = textNormalize;
368 }
369 }
370 if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Autoren")){
371 strAuthor = elWissName.getTextNormalize();
372 }
373 if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Rang")){
374 String strRank = elWissName.getTextNormalize();
375 rank = makeRank(strRank);
376 }
377 if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Zusätze")){
378 strSupplement = elWissName.getTextNormalize();
379 }
380 if(elWissName.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("wissName")){
381 try{
382 TaxonNameBase<?, ?> nameBase = parseNonviralNames(rank,strAuthor,strSupplement,elWissName);
383 if(nameBase.isProtectedTitleCache() == true){
384 logger.warn("Taxon " + nameBase.getTitleCache());
385 }
386
387 //TODO extract to method?
388 if(strSupplement != null){
389 nameBase.setAppendedPhrase(strSupplement);
390 }
391 if(strSupplement != null && strSupplement.equalsIgnoreCase("nom. illeg.")){
392 nameBase.addStatus(NomenclaturalStatus.NewInstance(NomenclaturalStatusType.ILLEGITIMATE()));
393 }
394 /**
395 * BFN does not want any name matching yet
396 */
397 // TaxonBase<?> taxonBase = null;
398 // //TODO find best matching Taxa
399 // Pager<TaxonNameBase> names = getNameService().findByTitle(null, nameBase.getTitleCache(), null, null, null, null, null, null);
400 // //TODO correct handling for pager
401 // List<TaxonNameBase> nameList = names.getRecords();
402 // if (nameList.isEmpty()){
403 // taxonBase = Taxon.NewInstance(nameBase, config.getSourceReference());
404 // }else{
405 // taxonBase = Taxon.NewInstance(nameList.get(0), config.getSourceReference());
406 // if (nameList.size()>1){
407 // logger.warn("More than 1 matching taxon name found for " + nameBase.getTitleCache());
408 // }
409 // }
410
411 Reference<?> microRef = config.isFillSecondList() ?
412 state.getSecondListSecRef():
413 state.getFirstListSecRef();
414 state.setCurrentMicroRef(microRef);
415 taxon = Taxon.NewInstance(nameBase, state.getCurrentMicroRef());
416 //set create and set path of nameSpace
417 Element parentElement = elWissName.getParentElement();
418 Element grandParentElement = parentElement.getParentElement();
419 String namespace = grandParentElement.getName() + ":" + parentElement.getName() + ":"+elWissName.getName() + ":" + uriNameSpace;
420 String microRefStr = microRef == null ? null : microRef.getTitle();
421 taxon.addImportSource(uniqueID, namespace, state.getCompleteSourceRef(), microRefStr);
422 } catch (UnknownCdmTypeException e) {
423 success.setValue(false);
424 }
425 }
426 }
427 return taxon;
428 }
429
430 /**
431 * Matches the XML attributes against CDM entities.<BR>
432 * Imports Scientific Name, Rank etc. and create a synonym.<br>
433 * <b>Existing synonym names won't be matched yet</b>
434 *
435 * @param taxon
436 * @param success
437 * @param obligatory
438 * @param bfnNamespace
439 * @param childElementName
440 * @param elSynonyms
441 * @param taxonId
442 * @param config
443 * @param state
444 */
445
446 @SuppressWarnings({ "unchecked" })
447 private void createOrUpdateSynonym(Taxon taxon, ResultWrapper<Boolean> success, boolean obligatory, Namespace bfnNamespace,
448 String childElementName, Element elSynonyms, String taxonId, BfnXmlImportState state) {
449
450 String childName;
451 List<Element> elSynonymList = elSynonyms.getChildren(childElementName, bfnNamespace);
452
453 for(Element elSyn:elSynonymList){
454 Rank rank = null;
455 String strAuthor = null;
456 String strSupplement = null;
457 childName = BfnXmlConstants.EL_WISSNAME;
458 Element elSynScientificName = XmlHelp.getSingleChildElement(success, elSyn, childName, bfnNamespace, obligatory);
459
460 childElementName = BfnXmlConstants.EL_NANTEIL;
461 List<Element> elSynDetails = elSynScientificName.getChildren(childElementName, bfnNamespace);
462
463 for(Element elSynDetail:elSynDetails){
464 if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH).equalsIgnoreCase("Rang")){
465 String strRank = elSynDetail.getTextNormalize();
466 rank = makeRank(strRank);
467 }
468 if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH).equalsIgnoreCase("Autoren")){
469 strAuthor = elSynDetail.getTextNormalize();
470 }
471 if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH, bfnNamespace).equalsIgnoreCase("Zusätze")){
472 strSupplement = elSynDetail.getTextNormalize();
473 }
474 if(elSynDetail.getAttributeValue(BfnXmlConstants.ATT_BEREICH).equalsIgnoreCase("wissName")){
475 try{
476 TaxonNameBase<?, ?> nameBase = parseNonviralNames(rank,strAuthor,strSupplement,elSynDetail);
477
478 //TODO find best matching Taxa
479 Synonym synonym = Synonym.NewInstance(nameBase, state.getCurrentMicroRef());
480 taxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF());
481
482 } catch (UnknownCdmTypeException e) {
483 logger.warn("Name with id " + taxonId + " has unknown nomenclatural code.");
484 success.setValue(false);
485 }
486
487 }
488
489 }
490 }
491 }
492
493
494 /**
495 *
496 * @param taxon
497 * @param bfnNamespace
498 * @param childElementName
499 * @param elVernacularName
500 * @param state
501 */
502 private void createOrUpdateVernacularName(Taxon taxon,
503 Namespace bfnNamespace, String childElementName,
504 Element elVernacularName, BfnXmlImportState state) {
505
506 List<Element> elVernacularNameList = elVernacularName.getChildren(childElementName, bfnNamespace);
507
508 TaxonDescription taxonDescription = getTaxonDescription(taxon, false, true);
509
510 for(Element elVernacular : elVernacularNameList){
511 Element child = elVernacular.getChild("TRIVIALNAME");
512 if(child != null){
513 makeCommonName(taxonDescription, child, state);
514 }
515 }
516
517 }
518
519 /**
520 *
521 * @param taxon
522 * @param bfnNamespace
523 * @param childElementName
524 * @param elInformations
525 * @param state
526 * @throws UnknownCdmTypeException
527 */
528
529 @SuppressWarnings("unchecked")
530 private void createOrUpdateInformation(Taxon taxon,
531 Namespace bfnNamespace, String childElementName,
532 Element elInformations,
533 BfnXmlImportState state){
534
535 List<Element> elInformationList = elInformations.getChildren(childElementName, bfnNamespace);
536
537 for(Element elInfo:elInformationList){
538 //check if geographical scope is Bund and import only these information for now
539 //TODO create several taxon descriptions for different geographical scope
540 if(elInfo.getName().equalsIgnoreCase(BfnXmlConstants.EL_BEZUGSRAUM) && elInfo.getAttributeValue("name").equalsIgnoreCase("Bund")){
541 childElementName = BfnXmlConstants.EL_IWERT;
542 TaxonDescription taxonDescription = getTaxonDescription(taxon, false, true);
543 UUID germanStateUUID;
544 try {
545 germanStateUUID = BfnXmlTransformer.getGermanStateUUID("Deutschland");
546 NamedArea area = (NamedArea)getTermService().load(germanStateUUID);
547 //FIXME GEOSCOPE_ID CANNOT BE NULL Exception
548 // taxonDescription.addGeoScope(area);
549 } catch (UnknownCdmTypeException e) {
550 // TODO Auto-generated catch block
551 e.printStackTrace();
552 }
553 List<Element> elInfoDetailList = elInfo.getChildren(childElementName, bfnNamespace);
554
555 for(Element elInfoDetail : elInfoDetailList){
556 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("RL Kat.")){
557 makeFeatures(taxonDescription, elInfoDetail, state, false);
558 }
559 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Kat. +/-")){
560 makeFeatures(taxonDescription, elInfoDetail, state, false);
561 }
562 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("aktuelle Bestandsstituation")){
563 makeFeatures(taxonDescription, elInfoDetail, state, false);
564 }
565 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("langfristiger Bestandstrend")){
566 makeFeatures(taxonDescription, elInfoDetail, state, false);
567 }
568 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("kurzfristiger Bestandstrend")){
569 makeFeatures(taxonDescription, elInfoDetail, state, false);
570 }
571 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Risikofaktoren")){
572 makeFeatures(taxonDescription, elInfoDetail, state, false);
573 }
574 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Verantwortlichkeit")){
575 makeFeatures(taxonDescription, elInfoDetail, state, false);
576 }
577 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("alte RL- Kat.")){
578 makeFeatures(taxonDescription, elInfoDetail, state, false);
579 }
580 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Neobiota")){
581 makeFeatures(taxonDescription, elInfoDetail, state, false);
582 }
583 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Eindeutiger Code")){
584 makeFeatures(taxonDescription, elInfoDetail, state, false);
585 }
586 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Kommentar zur Taxonomie")){
587 makeFeatures(taxonDescription, elInfoDetail, state, true);
588 }
589 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Kommentar zur Gefährdung")){
590 makeFeatures(taxonDescription, elInfoDetail, state, true);
591 }
592 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Sonderfälle")){
593 makeFeatures(taxonDescription, elInfoDetail, state, false);
594 }
595 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Letzter Nachweis")){
596 makeFeatures(taxonDescription, elInfoDetail, state, true);
597 }
598 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("Weitere Kommentare")){
599 makeFeatures(taxonDescription, elInfoDetail, state, true);
600 }
601 //create german federal states distribution status
602 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BW")){
603 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
604 }
605 //create german federal states distribution status
606 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BY")){
607 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
608 }
609 //create german federal states distribution status
610 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BE")){
611 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
612 }
613 //create german federal states distribution status
614 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("BB")){
615 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
616 }
617 //create german federal states distribution status
618 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HB")){
619 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
620 }
621 //create german federal states distribution status
622 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HH")){
623 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
624 }
625 //create german federal states distribution status
626 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("HE")){
627 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
628 }
629 //create german federal states distribution status
630 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("MV")){
631 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
632 }
633 //create german federal states distribution status
634 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("NI")){
635 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
636 }
637 //create german federal states distribution status
638 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("NW")){
639 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
640 }
641 //create german federal states distribution status
642 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("RP")){
643 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
644 }
645 //create german federal states distribution status
646 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SL")){
647 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
648 }
649 //create german federal states distribution status
650 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SN")){
651 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
652 }
653 //create german federal states distribution status
654 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("ST")){
655 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
656 }
657 //create german federal states distribution status
658 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("SH")){
659 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
660 }
661 //create german federal states distribution status
662 if(elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME).equalsIgnoreCase("TH")){
663 createGermanDistributionStatus(taxon, elInfoDetail, state, taxonDescription);
664 }
665 }
666 }
667 }
668 }
669
670
671 private void makeCommonName(TaxonDescription taxonDescription,
672 Element child, BfnXmlImportState state) {
673 String commonNameValue = child.getValue();
674 NamedArea area = getTermService().getAreaByTdwgAbbreviation("GER");
675 CommonTaxonName commonName = CommonTaxonName.NewInstance(commonNameValue, Language.GERMAN(), area);
676 taxonDescription.addElement(commonName);
677 }
678
679
680 /**
681 *
682 * @param taxonDescription
683 * @param elInfoDetail
684 * @param state
685 * @param isTextData
686 */
687 private void makeFeatures(
688 TaxonDescription taxonDescription,
689 Element elInfoDetail,
690 BfnXmlImportState state,
691 boolean isTextData) {
692
693 String transformedRlKatValue = null;
694 UUID featureUUID = null;
695 UUID stateTermUUID = null;
696 String strRlKatValue = elInfoDetail.getChild(BfnXmlConstants.EL_WERT).getValue();
697 String strRlKat = elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME);
698 boolean randomStateUUID = false;
699 try {
700 featureUUID = BfnXmlTransformer.getRedlistFeatureUUID(strRlKat);
701 transformedRlKatValue = BfnXmlTransformer.redListString2RedListCode(strRlKatValue);
702 } catch (UnknownCdmTypeException e) {
703 transformedRlKatValue = strRlKatValue;
704 }
705 Feature redListFeature = getFeature(state, featureUUID);
706 State rlState = null;
707 //if is text data a state is not needed
708 if(!isTextData){
709 try {
710 stateTermUUID = BfnXmlTransformer.getRedlistStateTermUUID(transformedRlKatValue, strRlKat);
711 } catch (UnknownCdmTypeException e) {
712 stateTermUUID = UUID.randomUUID();
713 randomStateUUID = true;
714 }
715 if(randomStateUUID || stateTermUUID == BfnXmlTransformer.stateTermEmpty){
716 if(stateTermUUID == BfnXmlTransformer.stateTermEmpty) {
717 transformedRlKatValue = "keine Angabe";
718 }
719 rlState = getStateTerm(state, stateTermUUID, transformedRlKatValue, transformedRlKatValue, transformedRlKatValue, null);
720 }else{
721 rlState = getStateTerm(state, stateTermUUID);
722 }
723 }
724 if(isTextData){
725 TextData textData = TextData.NewInstance(redListFeature);
726 textData.putText(Language.GERMAN(), strRlKatValue);
727 DescriptionElementBase descriptionElement = textData;
728 taxonDescription.addElement(descriptionElement);
729 }else{
730 CategoricalData catData = CategoricalData.NewInstance(rlState, redListFeature);
731 DescriptionElementBase descriptionElement = catData;
732 taxonDescription.addElement(descriptionElement);
733 }
734 }
735
736 /**
737 * Returns the rank represented by the rank element.<br>
738 * Returns <code>null</code> if the element is null.<br>
739 * Returns <code>null</code> if the code and the text are both either empty or do not exists.<br>
740 * Returns the rank represented by the code attribute, if the code attribute is not empty and could be resolved.<br>
741 * If the code could not be resolved it returns the rank represented most likely by the elements text.<br>
742 * Returns UNKNOWN_RANK if code attribute and element text could not be resolved.
743 * @param strRank bfn rank element
744 * @return
745 */
746 protected static Rank makeRank(String strRank){
747 Rank result;
748 if (strRank == null){
749 return null;
750 }
751 Rank codeRank = null;
752 try {
753 codeRank = BfnXmlTransformer.rankCode2Rank(strRank);
754 } catch (UnknownCdmTypeException e1) {
755 codeRank = Rank.UNKNOWN_RANK();
756 }
757 //codeRank exists
758 if ( (codeRank != null) && !codeRank.equals(Rank.UNKNOWN_RANK())){
759 result = codeRank;
760 }
761 //codeRank does not exist
762 else{
763 result = codeRank;
764 logger.warn("string rank used, because code rank does not exist or was not recognized: " + codeRank.getTitleCache()+" "+strRank);
765 }
766 return result;
767 }
768
769 /**
770 * @param rank
771 * @param strAuthor
772 * @param strSupplement
773 * @param elWissName
774 * @return
775 * @throws UnknownCdmTypeException
776 */
777 private TaxonNameBase<?, ?> parseNonviralNames(Rank rank, String strAuthor, String strSupplement, Element elWissName)
778 throws UnknownCdmTypeException {
779 TaxonNameBase<?,?> taxonNameBase = null;
780
781 String strScientificName = elWissName.getTextNormalize();
782 /**
783 *
784 * trim strScienctificName because sometimes
785 * getTextNormalize() does not removes all the
786 * whitespaces
787 *
788 **/
789 strScientificName = StringUtils.trim(strScientificName);
790 strScientificName = StringUtils.remove(strScientificName, "\u00a0");
791 strScientificName = StringUtils.remove(strScientificName, "\uc281");
792
793 if(strSupplement != null && !strSupplement.isEmpty()){
794 strScientificName = StringUtils.remove(strScientificName, strSupplement);
795 }
796 NonViralName<?> nonViralName = null;
797 NonViralNameParserImpl parser = NonViralNameParserImpl.NewInstance();
798 nonViralName = parser.parseFullName(strScientificName, nomenclaturalCode, rank);
799 if(nonViralName.hasProblem()){
800 for(ParserProblem p:nonViralName.getParsingProblems()){
801 logger.warn(++parsingProblemCounter + " " +nonViralName.getTitleCache() +" "+p.toString());
802 }
803 }
804 //check for parsed rank
805 Rank parsedRank = nonViralName.getRank();
806 if(parsedRank != rank){
807 nonViralName.setRank(rank);
808 }
809 //check for parsed author
810 String parsedAuthor = nonViralName.getAuthorshipCache();
811 strAuthor = StringUtils.trim(strAuthor);
812 parsedAuthor = StringUtils.trim(parsedAuthor);
813 if(parsedAuthor.equalsIgnoreCase(strAuthor)){
814 logger.info("Taxon " + nonViralName.getTitleCache() +":"
815 +"\t Author field: " + strAuthor +" and parsed AuthorshipCache: "+nonViralName.getAuthorshipCache());
816 }
817 taxonNameBase = nonViralName;
818 return taxonNameBase;
819 }
820
821 /**
822 * This method will match the BFN XML status to a distribution status
823 * and map it to the german federal state area. The vocabulary needs to be
824 * created first by the Importer, in order to map the terms correctly. Have a look
825 * for further details at the file BfnXmlImportAdditionalTerms.
826 *
827 *
828 * @param taxon, for saving the distribution and its status
829 * @param elInfoDetail, keeps the details from the import, in this case the distribution detail
830 * @param state, import state
831 * @param germanState, the abbreviated label for the German state
832 *
833 */
834 private void createGermanDistributionStatus(Taxon taxon, Element elInfoDetail, BfnXmlImportState state,
835 TaxonDescription taxonDescription){
836
837 String strDistributionValue = elInfoDetail.getChild(BfnXmlConstants.EL_WERT).getValue();
838 String strGermanState = elInfoDetail.getAttributeValue(BfnXmlConstants.ATT_STANDARDNAME);
839 //match DistributionValue
840 UUID matchedDistributionUUID = null;
841 PresenceAbsenceTerm status = null;
842 try {
843 matchedDistributionUUID = BfnXmlTransformer.matchDistributionValue(strDistributionValue);
844 DefinedTermBase load = getTermService().load(matchedDistributionUUID);
845 if(load.isInstanceOf(PresenceAbsenceTerm.class)) {
846 status = CdmBase.deproxy(load, PresenceAbsenceTerm.class);
847 }else{
848 logger.warn(strDistributionValue + " is not PresenceAbsence Term " + load.getTitleCache() + " " + load.getTermType().toString());
849 return;
850 }
851 } catch (UnknownCdmTypeException e1) {
852 logger.warn("could not match xml value "+ strDistributionValue +" to distribution status for "+strGermanState);
853 e1.printStackTrace();
854 return;
855 }
856 //load vocabulary and german state
857 UUID vocabularyUUID = null;
858 TermVocabulary vocabulary = null;
859 UUID stateUUID = null;
860
861 try {
862 stateUUID = BfnXmlTransformer.getGermanStateUUID(strGermanState);
863 } catch (UnknownCdmTypeException e1) {
864 logger.warn("could not match state" + strGermanState + " to UUID");
865 e1.printStackTrace();
866 return;
867 }
868 NamedArea area = (NamedArea)getTermService().load(stateUUID);
869
870 // try {
871 // vocabularyUUID = BfnXmlTransformer.getRedlistVocabularyUUID("Bundesländer");
872 // vocabulary = getVocabularyService().load(vocabularyUUID);
873 // } catch (UnknownCdmTypeException e) {
874 // logger.warn("could not load vocabulary");
875 // e.printStackTrace();
876 // return;
877 // }
878 // NamedArea area = null;
879 // for(Object term: vocabulary){
880 // //TODO match german state
881 // NamedArea narea = (NamedArea) term;
882 // Set<Representation> representations = narea.getRepresentations();
883 // for(Representation r:representations){
884 // if(r.getAbbreviatedLabel().equalsIgnoreCase(strGermanState)){
885 // area = narea;
886 // }
887 // }
888 //
889 // }
890 //create new taxon description
891 DescriptionElementBase descriptionElement = Distribution.NewInstance(area, status);
892 taxonDescription.addElement(descriptionElement);
893 }
894
895
896 @Override
897 public boolean doCheck(BfnXmlImportState state){
898 boolean result = true;
899 return result;
900 }
901
902 @Override
903 protected boolean isIgnore(BfnXmlImportState state){
904 return ! state.getConfig().isDoTaxonNames();
905 }
906 }