2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.io
.redlist
.bfnXml
.in
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.LinkedHashMap
;
15 import java
.util
.List
;
17 import java
.util
.UUID
;
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
;
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
;
68 //@Component("bfnXmlTaxonNameIO")
70 public class BfnXmlImportTaxonName
extends BfnXmlImportBase
{
72 private static final Logger logger
= Logger
.getLogger(BfnXmlImportTaxonName
.class);
74 private static NomenclaturalCode nomenclaturalCode
= null;
75 private static int parsingProblemCounter
= 0;
76 private Map
<Integer
, Taxon
> firstList
;
77 private Map
<Integer
, Taxon
> secondList
;
80 public BfnXmlImportTaxonName(){
86 @SuppressWarnings({"rawtypes" })
87 public void doInvoke(BfnXmlImportState state
){
88 ITaxonService taxonService
= getTaxonService();
90 BfnXmlImportConfigurator config
= state
.getConfig();
91 nomenclaturalCode
= config
.getNomenclaturalCode();
92 Element elDataSet
= getDataSetElement(config
);
94 Namespace bfnNamespace
= config
.getBfnXmlNamespace();
96 List
<?
> contentXML
= elDataSet
.getContent();
97 Element currentElement
= null;
98 for(Object object
:contentXML
){
100 if(object
instanceof Element
){
101 currentElement
= (Element
)object
;
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
);
122 * This method will parse the XML concept relationships and tries to map them into cdm relationship types.
124 * @param bfnNamespace
125 * @param currentElement
127 private void extractTaxonConceptRelationShips(Namespace bfnNamespace
, Element currentElement
) {
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
){
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
;
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
;
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;
157 * This if case only exists because it was decided not to have a included_in relationship type.
159 if(conceptStatusValue
.equalsIgnoreCase("<")){
160 taxon2
.addTaxonRelation(taxon1
, TaxonRelationshipType
.INCLUDES(), null, null);
163 taxonRelationType
= BfnXmlTransformer
.concept2TaxonRelation(conceptStatusValue
);
164 } catch (UnknownCdmTypeException e
) {
167 taxon1
.addTaxonRelation(taxon2
, taxonRelationType
, null, null);
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);
174 updatedTaxonList
.add(taxon2
);
175 updatedTaxonList
.add(taxon1
);
177 getTaxonService().saveOrUpdate(updatedTaxonList
);
178 logger
.info("taxon relationships imported...");
182 * This method stores the current imported maps in global variables to make
183 * them later available for matching the taxon relationships between these
189 private void prepareListforConceptImport(BfnXmlImportConfigurator config
,Map
<Integer
, Taxon
> taxonMap
) {
190 if(config
.isFillSecondList()){
191 secondList
= taxonMap
;
193 firstList
= taxonMap
;
200 * @param taxonService
203 * @param bfnNamespace
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);
214 String idNamespace
= "TaxonName";
216 childName
= BfnXmlConstants
.EL_TAXONYME
;
218 Element elTaxonNames
= XmlHelp
.getSingleChildElement(success
, elDataSet
, childName
, bfnNamespace
, obligatory
);
220 String bfnElementName
= BfnXmlConstants
.EL_TAXONYM
;
221 List
<Element
> elTaxonList
= elTaxonNames
.getChildren(bfnElementName
, bfnNamespace
);
224 for (Element elTaxon
: elTaxonList
){
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
);
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
);
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
);
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
);
256 taxonMap
.put(Integer
.parseInt(taxonId
), taxon
);
259 //Quick'n'dirty to set concept relationships between two imported list
260 prepareListforConceptImport(config
, taxonMap
);
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();
270 return savedTaxonMap
;
277 * This will put the prior imported list into a classification
280 * @param taxonService
282 * @param savedTaxonMap
283 * @param currentElement
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();
294 // if(classificationName == null){
295 // classificationName = config.getClassificationName();
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;
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);
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);
325 return isNewClassification
;
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>
338 * @param bfnNamespace
340 * @param childElementName
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
) {
351 List
<Element
> elWissNameList
= elTaxonName
.getChildren(childElementName
, bfnNamespace
);
353 String strAuthor
= null;
354 String strSupplement
= null;
356 String uniqueID
= null;
357 String uriNameSpace
= null;
358 // Long uniqueID = null;
359 for(Element elWissName
:elWissNameList
){
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
)){
367 uniqueID
= textNormalize
;
370 if(elWissName
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
, bfnNamespace
).equalsIgnoreCase("Autoren")){
371 strAuthor
= elWissName
.getTextNormalize();
373 if(elWissName
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
, bfnNamespace
).equalsIgnoreCase("Rang")){
374 String strRank
= elWissName
.getTextNormalize();
375 rank
= makeRank(strRank
);
377 if(elWissName
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
, bfnNamespace
).equalsIgnoreCase("Zusätze")){
378 strSupplement
= elWissName
.getTextNormalize();
380 if(elWissName
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
, bfnNamespace
).equalsIgnoreCase("wissName")){
382 TaxonNameBase
<?
, ?
> nameBase
= parseNonviralNames(rank
,strAuthor
,strSupplement
,elWissName
);
383 if(nameBase
.isProtectedTitleCache() == true){
384 logger
.warn("Taxon " + nameBase
.getTitleCache());
387 //TODO extract to method?
388 if(strSupplement
!= null){
389 nameBase
.setAppendedPhrase(strSupplement
);
391 if(strSupplement
!= null && strSupplement
.equalsIgnoreCase("nom. illeg.")){
392 nameBase
.addStatus(NomenclaturalStatus
.NewInstance(NomenclaturalStatusType
.ILLEGITIMATE()));
395 * BFN does not want any name matching yet
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());
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());
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);
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>
438 * @param bfnNamespace
439 * @param childElementName
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
) {
451 List
<Element
> elSynonymList
= elSynonyms
.getChildren(childElementName
, bfnNamespace
);
453 for(Element elSyn
:elSynonymList
){
455 String strAuthor
= null;
456 String strSupplement
= null;
457 childName
= BfnXmlConstants
.EL_WISSNAME
;
458 Element elSynScientificName
= XmlHelp
.getSingleChildElement(success
, elSyn
, childName
, bfnNamespace
, obligatory
);
460 childElementName
= BfnXmlConstants
.EL_NANTEIL
;
461 List
<Element
> elSynDetails
= elSynScientificName
.getChildren(childElementName
, bfnNamespace
);
463 for(Element elSynDetail
:elSynDetails
){
464 if(elSynDetail
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
).equalsIgnoreCase("Rang")){
465 String strRank
= elSynDetail
.getTextNormalize();
466 rank
= makeRank(strRank
);
468 if(elSynDetail
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
).equalsIgnoreCase("Autoren")){
469 strAuthor
= elSynDetail
.getTextNormalize();
471 if(elSynDetail
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
, bfnNamespace
).equalsIgnoreCase("Zusätze")){
472 strSupplement
= elSynDetail
.getTextNormalize();
474 if(elSynDetail
.getAttributeValue(BfnXmlConstants
.ATT_BEREICH
).equalsIgnoreCase("wissName")){
476 TaxonNameBase
<?
, ?
> nameBase
= parseNonviralNames(rank
,strAuthor
,strSupplement
,elSynDetail
);
478 //TODO find best matching Taxa
479 Synonym synonym
= Synonym
.NewInstance(nameBase
, state
.getCurrentMicroRef());
480 taxon
.addSynonym(synonym
, SynonymRelationshipType
.SYNONYM_OF());
482 } catch (UnknownCdmTypeException e
) {
483 logger
.warn("Name with id " + taxonId
+ " has unknown nomenclatural code.");
484 success
.setValue(false);
497 * @param bfnNamespace
498 * @param childElementName
499 * @param elVernacularName
502 private void createOrUpdateVernacularName(Taxon taxon
,
503 Namespace bfnNamespace
, String childElementName
,
504 Element elVernacularName
, BfnXmlImportState state
) {
506 List
<Element
> elVernacularNameList
= elVernacularName
.getChildren(childElementName
, bfnNamespace
);
508 TaxonDescription taxonDescription
= getTaxonDescription(taxon
, false, true);
510 for(Element elVernacular
: elVernacularNameList
){
511 Element child
= elVernacular
.getChild("TRIVIALNAME");
513 makeCommonName(taxonDescription
, child
, state
);
522 * @param bfnNamespace
523 * @param childElementName
524 * @param elInformations
526 * @throws UnknownCdmTypeException
529 @SuppressWarnings("unchecked")
530 private void createOrUpdateInformation(Taxon taxon
,
531 Namespace bfnNamespace
, String childElementName
,
532 Element elInformations
,
533 BfnXmlImportState state
){
535 List
<Element
> elInformationList
= elInformations
.getChildren(childElementName
, bfnNamespace
);
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
;
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
553 List
<Element
> elInfoDetailList
= elInfo
.getChildren(childElementName
, bfnNamespace
);
555 for(Element elInfoDetail
: elInfoDetailList
){
556 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("RL Kat.")){
557 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
559 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Kat. +/-")){
560 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
562 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("aktuelle Bestandsstituation")){
563 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
565 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("langfristiger Bestandstrend")){
566 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
568 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("kurzfristiger Bestandstrend")){
569 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
571 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Risikofaktoren")){
572 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
574 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Verantwortlichkeit")){
575 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
577 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("alte RL- Kat.")){
578 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
580 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Neobiota")){
581 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
583 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Eindeutiger Code")){
584 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
586 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Kommentar zur Taxonomie")){
587 makeFeatures(taxonDescription
, elInfoDetail
, state
, true);
589 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Kommentar zur Gefährdung")){
590 makeFeatures(taxonDescription
, elInfoDetail
, state
, true);
592 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Sonderfälle")){
593 makeFeatures(taxonDescription
, elInfoDetail
, state
, false);
595 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Letzter Nachweis")){
596 makeFeatures(taxonDescription
, elInfoDetail
, state
, true);
598 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("Weitere Kommentare")){
599 makeFeatures(taxonDescription
, elInfoDetail
, state
, true);
601 //create german federal states distribution status
602 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("BW")){
603 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
605 //create german federal states distribution status
606 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("BY")){
607 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
609 //create german federal states distribution status
610 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("BE")){
611 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
613 //create german federal states distribution status
614 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("BB")){
615 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
617 //create german federal states distribution status
618 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("HB")){
619 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
621 //create german federal states distribution status
622 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("HH")){
623 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
625 //create german federal states distribution status
626 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("HE")){
627 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
629 //create german federal states distribution status
630 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("MV")){
631 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
633 //create german federal states distribution status
634 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("NI")){
635 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
637 //create german federal states distribution status
638 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("NW")){
639 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
641 //create german federal states distribution status
642 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("RP")){
643 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
645 //create german federal states distribution status
646 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("SL")){
647 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
649 //create german federal states distribution status
650 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("SN")){
651 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
653 //create german federal states distribution status
654 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("ST")){
655 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
657 //create german federal states distribution status
658 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("SH")){
659 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
661 //create german federal states distribution status
662 if(elInfoDetail
.getAttributeValue(BfnXmlConstants
.ATT_STANDARDNAME
).equalsIgnoreCase("TH")){
663 createGermanDistributionStatus(taxon
, elInfoDetail
, state
, taxonDescription
);
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
);
682 * @param taxonDescription
683 * @param elInfoDetail
687 private void makeFeatures(
688 TaxonDescription taxonDescription
,
689 Element elInfoDetail
,
690 BfnXmlImportState state
,
691 boolean isTextData
) {
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;
700 featureUUID
= BfnXmlTransformer
.getRedlistFeatureUUID(strRlKat
);
701 transformedRlKatValue
= BfnXmlTransformer
.redListString2RedListCode(strRlKatValue
);
702 } catch (UnknownCdmTypeException e
) {
703 transformedRlKatValue
= strRlKatValue
;
705 Feature redListFeature
= getFeature(state
, featureUUID
);
706 State rlState
= null;
707 //if is text data a state is not needed
710 stateTermUUID
= BfnXmlTransformer
.getRedlistStateTermUUID(transformedRlKatValue
, strRlKat
);
711 } catch (UnknownCdmTypeException e
) {
712 stateTermUUID
= UUID
.randomUUID();
713 randomStateUUID
= true;
715 if(randomStateUUID
|| stateTermUUID
== BfnXmlTransformer
.stateTermEmpty
){
716 if(stateTermUUID
== BfnXmlTransformer
.stateTermEmpty
) {
717 transformedRlKatValue
= "keine Angabe";
719 rlState
= getStateTerm(state
, stateTermUUID
, transformedRlKatValue
, transformedRlKatValue
, transformedRlKatValue
, null);
721 rlState
= getStateTerm(state
, stateTermUUID
);
725 TextData textData
= TextData
.NewInstance(redListFeature
);
726 textData
.putText(Language
.GERMAN(), strRlKatValue
);
727 DescriptionElementBase descriptionElement
= textData
;
728 taxonDescription
.addElement(descriptionElement
);
730 CategoricalData catData
= CategoricalData
.NewInstance(rlState
, redListFeature
);
731 DescriptionElementBase descriptionElement
= catData
;
732 taxonDescription
.addElement(descriptionElement
);
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
746 protected static Rank
makeRank(String strRank
){
748 if (strRank
== null){
751 Rank codeRank
= null;
753 codeRank
= BfnXmlTransformer
.rankCode2Rank(strRank
);
754 } catch (UnknownCdmTypeException e1
) {
755 codeRank
= Rank
.UNKNOWN_RANK();
758 if ( (codeRank
!= null) && !codeRank
.equals(Rank
.UNKNOWN_RANK())){
761 //codeRank does not exist
764 logger
.warn("string rank used, because code rank does not exist or was not recognized: " + codeRank
.getTitleCache()+" "+strRank
);
772 * @param strSupplement
775 * @throws UnknownCdmTypeException
777 private TaxonNameBase
<?
, ?
> parseNonviralNames(Rank rank
, String strAuthor
, String strSupplement
, Element elWissName
)
778 throws UnknownCdmTypeException
{
779 TaxonNameBase
<?
,?
> taxonNameBase
= null;
781 String strScientificName
= elWissName
.getTextNormalize();
784 * trim strScienctificName because sometimes
785 * getTextNormalize() does not removes all the
789 strScientificName
= StringUtils
.trim(strScientificName
);
790 strScientificName
= StringUtils
.remove(strScientificName
, "\u00a0");
791 strScientificName
= StringUtils
.remove(strScientificName
, "\uc281");
793 if(strSupplement
!= null && !strSupplement
.isEmpty()){
794 strScientificName
= StringUtils
.remove(strScientificName
, strSupplement
);
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());
804 //check for parsed rank
805 Rank parsedRank
= nonViralName
.getRank();
806 if(parsedRank
!= rank
){
807 nonViralName
.setRank(rank
);
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());
817 taxonNameBase
= nonViralName
;
818 return taxonNameBase
;
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.
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
834 private void createGermanDistributionStatus(Taxon taxon
, Element elInfoDetail
, BfnXmlImportState state
,
835 TaxonDescription taxonDescription
){
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;
843 matchedDistributionUUID
= BfnXmlTransformer
.matchDistributionValue(strDistributionValue
);
844 DefinedTermBase load
= getTermService().load(matchedDistributionUUID
);
845 if(load
.isInstanceOf(PresenceAbsenceTerm
.class)) {
846 status
= CdmBase
.deproxy(load
, PresenceAbsenceTerm
.class);
848 logger
.warn(strDistributionValue
+ " is not PresenceAbsence Term " + load
.getTitleCache() + " " + load
.getTermType().toString());
851 } catch (UnknownCdmTypeException e1
) {
852 logger
.warn("could not match xml value "+ strDistributionValue
+" to distribution status for "+strGermanState
);
853 e1
.printStackTrace();
856 //load vocabulary and german state
857 UUID vocabularyUUID
= null;
858 TermVocabulary vocabulary
= null;
859 UUID stateUUID
= null;
862 stateUUID
= BfnXmlTransformer
.getGermanStateUUID(strGermanState
);
863 } catch (UnknownCdmTypeException e1
) {
864 logger
.warn("could not match state" + strGermanState
+ " to UUID");
865 e1
.printStackTrace();
868 NamedArea area
= (NamedArea
)getTermService().load(stateUUID
);
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();
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)){
890 //create new taxon description
891 DescriptionElementBase descriptionElement
= Distribution
.NewInstance(area
, status
);
892 taxonDescription
.addElement(descriptionElement
);
897 public boolean doCheck(BfnXmlImportState state
){
898 boolean result
= true;
903 protected boolean isIgnore(BfnXmlImportState state
){
904 return ! state
.getConfig().isDoTaxonNames();