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
.tcsxml
.in
;
12 import java
.util
.ArrayList
;
13 import java
.util
.Collection
;
14 import java
.util
.List
;
17 import org
.apache
.log4j
.Logger
;
18 import org
.jdom
.Element
;
19 import org
.jdom
.Namespace
;
20 import org
.springframework
.stereotype
.Component
;
22 import eu
.etaxonomy
.cdm
.common
.ResultWrapper
;
23 import eu
.etaxonomy
.cdm
.common
.XmlHelp
;
24 import eu
.etaxonomy
.cdm
.io
.common
.ICdmIO
;
25 import eu
.etaxonomy
.cdm
.io
.common
.IImportConfigurator
;
26 import eu
.etaxonomy
.cdm
.io
.common
.ImportHelper
;
27 import eu
.etaxonomy
.cdm
.io
.common
.MapWrapper
;
28 import eu
.etaxonomy
.cdm
.io
.tcsxml
.TcsXmlTransformer
;
29 import eu
.etaxonomy
.cdm
.model
.agent
.INomenclaturalAuthor
;
30 import eu
.etaxonomy
.cdm
.model
.agent
.Person
;
31 import eu
.etaxonomy
.cdm
.model
.agent
.Team
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
33 import eu
.etaxonomy
.cdm
.model
.name
.CultivarPlantName
;
34 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
35 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
36 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
37 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
38 import eu
.etaxonomy
.cdm
.model
.name
.ZoologicalName
;
39 import eu
.etaxonomy
.cdm
.model
.reference
.IGeneric
;
40 import eu
.etaxonomy
.cdm
.model
.reference
.INomenclaturalReference
;
41 import eu
.etaxonomy
.cdm
.model
.reference
.ReferenceBase
;
42 import eu
.etaxonomy
.cdm
.strategy
.exceptions
.UnknownCdmTypeException
;
44 @Component("tcsXmlTaxonNameIO")
45 public class TcsXmlTaxonNameImport
extends TcsXmlImportBase
implements ICdmIO
<TcsXmlImportState
> {
46 private static final Logger logger
= Logger
.getLogger(TcsXmlTaxonNameImport
.class);
48 private static int modCount
= 5000;
50 public TcsXmlTaxonNameImport(){
55 public boolean doCheck(TcsXmlImportState state
){
56 boolean result
= true;
57 logger
.warn("BasionymRelations not yet implemented");
58 logger
.warn("Checking for TaxonNames not yet implemented");
59 //result &= checkArticlesWithoutJournal(tcsConfig);
60 //result &= checkPartOfJournal(tcsConfig);
65 //@SuppressWarnings("unchecked")
67 public boolean doInvoke(TcsXmlImportState state
){
69 logger
.info("start make TaxonNames ...");
70 MapWrapper
<Person
> authorMap
= (MapWrapper
<Person
>)state
.getStore(ICdmIO
.TEAM_STORE
);
71 MapWrapper
<TaxonNameBase
> taxonNameMap
= (MapWrapper
<TaxonNameBase
>)state
.getStore(ICdmIO
.TAXONNAME_STORE
);
72 MapWrapper
<ReferenceBase
> referenceMap
= (MapWrapper
<ReferenceBase
>)state
.getStore(ICdmIO
.REFERENCE_STORE
);
74 ResultWrapper
<Boolean
> success
= ResultWrapper
.NewInstance(true);
77 String idNamespace
= "TaxonName";
79 TcsXmlImportConfigurator config
= state
.getConfig();
80 Element elDataSet
= getDataSetElement(config
);
81 Namespace tcsNamespace
= config
.getTcsXmlNamespace();
83 childName
= "TaxonNames";
85 Element elTaxonNames
= XmlHelp
.getSingleChildElement(success
, elDataSet
, childName
, tcsNamespace
, obligatory
);
87 String tcsElementName
= "TaxonName";
88 List
<Element
> elTaxonNameList
= (List
<Element
>)elTaxonNames
.getChildren(tcsElementName
, tcsNamespace
);
92 for (Element elTaxonName
: elTaxonNameList
){
93 if ((++i
% modCount
) == 0){ logger
.info("Names handled: " + (i
-1));}
94 List
<String
> elementList
= new ArrayList
<String
>();
96 //create TaxonName element
97 String strId
= elTaxonName
.getAttributeValue("id");
98 String strNomenclaturalCode
= elTaxonName
.getAttributeValue("nomenclaturalCode");
102 Element elRank
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
103 Rank rank
= makeRank(elRank
);
104 elementList
.add(childName
.toString());
108 TaxonNameBase
<?
,?
> nameBase
;
109 NomenclaturalCode nomCode
= TcsXmlTransformer
.nomCodeString2NomCode(strNomenclaturalCode
);
110 if (nomCode
!= null){
111 nameBase
= nomCode
.getNewTaxonNameInstance(rank
);
113 nameBase
= NonViralName
.NewInstance(rank
);
115 childName
= "Simple";
117 Element elSimple
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
118 String simple
= (elSimple
== null)?
"" : elSimple
.getTextNormalize();
119 nameBase
.setTitleCache(simple
, false);
120 elementList
.add(childName
.toString());
122 childName
= "CanonicalName";
124 Element elCanonicalName
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
125 makeCanonicalName(nameBase
, elCanonicalName
, taxonNameMap
, success
);
126 elementList
.add(childName
.toString());
128 childName
= "CanonicalAuthorship";
130 Element elCanonicalAuthorship
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
131 makeCanonicalAuthorship(nameBase
, elCanonicalAuthorship
, authorMap
, success
);
132 elementList
.add(childName
.toString());
134 childName
= "PublishedIn";
136 Element elPublishedIn
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
137 makePublishedIn(nameBase
, elPublishedIn
, referenceMap
, success
);
138 elementList
.add(childName
.toString());
142 Element elYear
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
143 makeYear(nameBase
, elYear
, success
);
144 elementList
.add(childName
.toString());
146 childName
= "MicroReference";
148 Element elMicroReference
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
149 makeMicroReference(nameBase
, elMicroReference
, success
);
150 elementList
.add(childName
.toString());
152 childName
= "Typification";
154 Element elTypification
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
155 makeTypification(nameBase
, elTypification
, success
);
156 elementList
.add(childName
.toString());
158 childName
= "PublicationStatus";
160 Element elPublicationStatus
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
161 makePublicationStatus(nameBase
, elPublicationStatus
, success
);
162 elementList
.add(childName
.toString());
164 childName
= "ProviderLink";
166 Element elProviderLink
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
167 makeProviderLink(nameBase
, elProviderLink
, success
);
168 elementList
.add(childName
.toString());
170 childName
= "ProviderSpecificData";
172 Element elProviderSpecificData
= XmlHelp
.getSingleChildElement(success
, elTaxonName
, childName
, tcsNamespace
, obligatory
);
173 makeProviderSpecificData(nameBase
, elProviderSpecificData
, success
);
174 elementList
.add(childName
.toString());
177 ImportHelper
.setOriginalSource(nameBase
, config
.getSourceReference(), strId
, idNamespace
);
179 taxonNameMap
.put(strId
, nameBase
);
181 } catch (UnknownCdmTypeException e
) {
182 logger
.warn("Name with id " + strId
+ " has unknown nomenclatural code.");
183 success
.setValue(false);
186 logger
.info(i
+ " names handled");
187 Collection
<?
extends TaxonNameBase
> col
= taxonNameMap
.objects();
188 getNameService().save((Collection
)col
);
190 logger
.info("end makeTaxonNames ...");
191 return success
.getValue();
196 * Returns the rank represented by the rank element.<br>
197 * Returns <code>null</code> if the element is null.<br>
198 * Returns <code>null</code> if the code and the text are both either empty or do not exists.<br>
199 * Returns the rank represented by the code attribute, if the code attribute is not empty and could be resolved.<br>
200 * If the code could not be resolved it returns the rank represented most likely by the elements text.<br>
201 * Returns UNKNOWN_RANK if code attribute and element text could not be resolved.
202 * @param elRank tcs rank element
205 protected static Rank
makeRank(Element elRank
){
210 String strRankCode
= elRank
.getAttributeValue("code");
211 String strRankString
= elRank
.getTextNormalize();
212 if (strRankCode
== null || "".equals(strRankCode
.trim()) &&
213 strRankString
== null || "".equals(strRankString
.trim())
218 Rank codeRank
= null;
220 codeRank
= TcsXmlTransformer
.rankCode2Rank(strRankCode
);
221 } catch (UnknownCdmTypeException e1
) {
222 codeRank
= Rank
.UNKNOWN_RANK();
224 Rank stringRank
= null;
226 boolean useUnknown
= true;
227 stringRank
= Rank
.getRankByNameOrAbbreviation(strRankString
, useUnknown
);
228 } catch (UnknownCdmTypeException e1
) {
229 //does not happen because of useUnknown = true
233 if (! (codeRank
== null) && ! codeRank
.equals(Rank
.UNKNOWN_RANK())){
235 if (! codeRank
.equals(stringRank
) && ! stringRank
.equals(Rank
.UNKNOWN_RANK())){
236 logger
.warn("code rank and string rank are unequal. code: " + codeRank
.getLabel() + stringRank
.getLabel());
239 //codeRank does not exist
242 logger
.warn("string rank used, because code rank does not exist or was not recognized: " + stringRank
.getLabel());
247 private void makeCanonicalName(TaxonNameBase name
, Element elCanonicalName
, MapWrapper
<TaxonNameBase
> taxonNameMap
, ResultWrapper
<Boolean
> success
){
248 boolean cacheProtected
= false;
250 if (elCanonicalName
== null){
253 Namespace ns
= elCanonicalName
.getNamespace();
255 String childName
= "Simple";
256 boolean obligatory
= true;
257 Element elSimple
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
258 String simple
= (elSimple
== null)?
"" : elSimple
.getTextNormalize();
259 name
.setFullTitleCache(simple
, cacheProtected
);
261 if (name
instanceof NonViralName
<?
>){
262 NonViralName
<?
> nonViralName
= (NonViralName
<?
>)name
;
263 childName
= "Uninomial";
265 Element elUninomial
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
266 String uninomial
= (elUninomial
== null)?
"" : elUninomial
.getTextNormalize();
267 if (! uninomial
.trim().equals("")){
268 nonViralName
.setGenusOrUninomial(uninomial
);
269 if (nonViralName
.getRank() != null && nonViralName
.getRank().isLower(Rank
.GENUS())){ // TODO check
270 logger
.warn("Name " + simple
+ " lower then 'genus' but has a canonical name part 'Uninomial'.");
273 testNoMoreElements();
277 Element elGenus
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
278 String genus
= (elGenus
== null)?
"" : elGenus
.getTextNormalize();
279 //TODO do Attributes reference
280 makeGenusReferenceType(name
, elGenus
, taxonNameMap
, success
);
281 if (! genus
.trim().equals("")){
282 nonViralName
.setGenusOrUninomial(genus
);
283 if (nonViralName
.getRank() != null && ! nonViralName
.getRank().isLower(Rank
.GENUS() )){ // TODO check
284 logger
.warn("Name " + simple
+ " is not lower then 'genus' but has canonical name part 'Genus'.");
288 childName
= "InfragenericEpithet";
290 Element elInfrageneric
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
291 String infraGenericEpithet
= (elInfrageneric
== null)?
"" : elInfrageneric
.getTextNormalize();
292 if (! infraGenericEpithet
.trim().equals("")){
293 nonViralName
.setInfraGenericEpithet(infraGenericEpithet
);
294 if (nonViralName
.getRank() != null && ! name
.getRank().isInfraGeneric()){
295 logger
.warn("Name " + simple
+ " is not infra generic but has canonical name part 'InfragenericEpithet'.");
298 testNoMoreElements();
300 childName
= "SpecificEpithet";
302 Element elSpecificEpithet
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
303 String specificEpithet
= (elSpecificEpithet
== null)?
"" : elSpecificEpithet
.getTextNormalize();
304 if (! specificEpithet
.trim().equals("")){
305 nonViralName
.setSpecificEpithet(specificEpithet
);
306 if (nonViralName
.getRank() != null && name
.getRank().isHigher(Rank
.SPECIES()) ){
307 logger
.warn("Name " + simple
+ " is not species or below but has canonical name part 'SpecificEpithet'.");
310 testNoMoreElements();
312 childName
= "InfraspecificEpithet";
314 Element elInfraspecificEpithet
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
315 String infraspecificEpithet
= (elInfraspecificEpithet
== null)?
"" : elInfraspecificEpithet
.getTextNormalize();
316 if (! infraspecificEpithet
.trim().equals("")){
317 nonViralName
.setInfraSpecificEpithet(infraspecificEpithet
);
318 if (nonViralName
.getRank() != null && ! name
.isInfraSpecific() ){
319 logger
.warn("Name " + simple
+ " is not infraspecific but has canonical name part 'InfraspecificEpithet'.");
322 testNoMoreElements();
326 //logger.warn("Non NonViralNames not yet supported by makeCanonicalName");
330 childName
= "CultivarNameGroup";
332 Element elCultivarNameGroup
= XmlHelp
.getSingleChildElement(success
, elCanonicalName
, childName
, ns
, obligatory
);
333 String cultivarNameGroup
= (elCultivarNameGroup
== null)?
"" : elCultivarNameGroup
.getTextNormalize();
334 if (! "".equals(cultivarNameGroup
.trim())){
335 if (name
instanceof CultivarPlantName
){
338 logger
.warn("Non cultivar name has 'cultivar name group' element. Omitted");
344 protected void testNoMoreElements(){
346 //logger.info("testNoMoreElements Not yet implemented");
349 private void makeCultivarName(){
351 //logger.warn("'makeCultivarName' Not yet implemented");
354 private void makeGenusReferenceType(TaxonNameBase name
, Element elGenus
, MapWrapper
<TaxonNameBase
> taxonNameMap
, ResultWrapper
<Boolean
> success
){
355 if(name
instanceof NonViralName
){
356 NonViralName nonViralName
= (NonViralName
)name
;
357 if (elGenus
!= null && name
!= null){
358 TaxonNameBase genusReferenceName
;
360 Class
<?
extends NonViralName
> clazz
= NonViralName
.class;
361 genusReferenceName
= makeReferenceType(elGenus
, clazz
, taxonNameMap
, success
);
362 NonViralName nvGenusReference
= (NonViralName
)genusReferenceName
;
363 //Genus is stored either in Genus part (if ref) or in titleCache (if plain text)
364 String genus
= nvGenusReference
.getGenusOrUninomial()!= null ? nvGenusReference
.getGenusOrUninomial(): genusReferenceName
.getTitleCache();
365 nonViralName
.setGenusOrUninomial(genus
);
367 logger
.warn("Missing Genus information");
370 //TODO (can be changed if Viral Name also has Genus in future
371 //logger.warn("Genus ref type for Viral Name not implemented yet");
377 @SuppressWarnings("unchecked")
378 private INomenclaturalAuthor
makeNameCitation(Element elNameCitation
, MapWrapper
<Person
> authorMap
, ResultWrapper
<Boolean
> success
){
379 INomenclaturalAuthor result
= null;
382 if (elNameCitation
!= null){
383 Namespace ns
= elNameCitation
.getNamespace();
385 childName
= "Authors";
387 Element elAuthors
= XmlHelp
.getSingleChildElement(success
, elNameCitation
, childName
, ns
, obligatory
);
388 testNoMoreElements();
390 if (elAuthors
!= null){
391 childName
= "AgentName";
392 List
<Element
> elAgentList
= elAuthors
.getChildren(childName
, ns
);
393 Team team
= Team
.NewInstance();
395 if (elAgentList
.size() > 1){
396 for(Element elAgent
: elAgentList
){
397 Person teamMember
= makeAgent(elAgent
, ns
, authorMap
, success
);
398 team
.addTeamMember(teamMember
);
400 }else if(elAgentList
.size() == 1){
401 result
= makeAgent(elAgentList
.get(0), ns
, authorMap
, success
);
404 childName
= "Simple";
406 Element elSimple
= XmlHelp
.getSingleChildElement(success
, elNameCitation
, childName
, ns
, obligatory
);
407 String simple
= (elSimple
== null)?
"" : elSimple
.getTextNormalize();
408 result
= Team
.NewInstance();
409 result
.setNomenclaturalTitle(simple
);
415 private Person
makeAgent(Element elAgentName
, Namespace ns
, MapWrapper
<Person
> agentMap
, ResultWrapper
<Boolean
> success
){
416 Person result
= null;
417 if (elAgentName
!= null){
418 String authorTitle
= elAgentName
.getTextNormalize();
419 result
= Person
.NewTitledInstance(authorTitle
);
420 Class
<?
extends Person
> clazz
= Person
.class;
421 result
= makeReferenceType(elAgentName
, clazz
, agentMap
, success
);
428 private void makeCanonicalAuthorship(TaxonNameBase name
, Element elCanonicalAuthorship
, MapWrapper
<Person
> authorMap
, ResultWrapper
<Boolean
> success
){
429 if (elCanonicalAuthorship
!= null){
430 Namespace ns
= elCanonicalAuthorship
.getNamespace();
432 if (name
instanceof NonViralName
){
433 NonViralName nonViralName
= (NonViralName
)name
;
435 String childName
= "Simple";
436 boolean obligatory
= true;
437 Element elSimple
= XmlHelp
.getSingleChildElement(success
, elCanonicalAuthorship
, childName
, ns
, obligatory
);
438 String simple
= (elSimple
== null)?
"" : elSimple
.getTextNormalize();
440 //logger.warn("authorship cache cache protected not yet implemented");
441 //nonViralName.setAuthorshipCache(simple, cacheProtected);
443 childName
= "Authorship";
445 Element elAuthorship
= XmlHelp
.getSingleChildElement(success
, elCanonicalAuthorship
, childName
, ns
, obligatory
);
446 INomenclaturalAuthor author
= makeNameCitation(elAuthorship
, authorMap
, success
);
447 nonViralName
.setCombinationAuthorTeam(author
);
448 testNoMoreElements();
450 childName
= "BasionymAuthorship";
452 Element elBasionymAuthorship
= XmlHelp
.getSingleChildElement(success
, elCanonicalAuthorship
, childName
, ns
, obligatory
);
453 INomenclaturalAuthor basionymAuthor
= makeNameCitation(elBasionymAuthorship
, authorMap
, success
);
454 nonViralName
.setBasionymAuthorTeam(basionymAuthor
);
455 testNoMoreElements();
457 childName
= "CombinationAuthorship";
459 Element elCombinationAuthorship
= XmlHelp
.getSingleChildElement(success
, elCanonicalAuthorship
, childName
, ns
, obligatory
);
460 INomenclaturalAuthor combinationAuthor
= makeNameCitation(elCombinationAuthorship
, authorMap
,success
);
461 nonViralName
.setCombinationAuthorTeam(combinationAuthor
);
462 testNoMoreElements();
464 if (elAuthorship
!= null && (elBasionymAuthorship
!= null || elCombinationAuthorship
!= null) ){
465 logger
.warn("Authorship and (BasionymAuthorship or CombinationAuthorship) must not exist at the same time in CanonicalAuthorship");
466 success
.setValue(false);
473 private void makePublishedIn(TaxonNameBase name
, Element elPublishedIn
, MapWrapper
<ReferenceBase
> referenceMap
, ResultWrapper
<Boolean
> success
){
474 if (elPublishedIn
!= null && name
!= null){
475 Class
<?
extends ReferenceBase
> clazz
= ReferenceBase
.class;
476 ReferenceBase ref
= makeReferenceType(elPublishedIn
, clazz
, referenceMap
, success
);
477 if (ref
instanceof INomenclaturalReference
){
478 name
.setNomenclaturalReference(ref
);
480 logger
.warn("Reference is not of type INomenclaturalReference and could not be added to the name " + name
.getTitleCache());
482 }else if (name
== null){
483 logger
.warn("TaxonName must not be 'null'");
484 success
.setValue(false);
489 private void makeYear(TaxonNameBase name
, Element elYear
, ResultWrapper
<Boolean
> success
){
491 String year
= elYear
.getTextNormalize();
492 if (name
instanceof ZoologicalName
){
493 ((ZoologicalName
)name
).setPublicationYear(getIntegerYear(year
));
495 logger
.warn("Year can be set only for a zoological name");
500 private Integer
getIntegerYear(String year
){
502 Integer result
= Integer
.valueOf(year
);
504 } catch (NumberFormatException e
) {
505 logger
.warn("Year string could not be parsed. Set = 9999 instead");
511 private void makeMicroReference(TaxonNameBase name
, Element elMicroReference
, ResultWrapper
<Boolean
> success
){
512 if (elMicroReference
!= null){
513 String microReference
= elMicroReference
.getTextNormalize();
514 name
.setNomenclaturalMicroReference(microReference
);
519 private void makeTypification(TaxonNameBase name
, Element elTypifiacation
, ResultWrapper
<Boolean
> success
){
520 if (elTypifiacation
!= null){
521 //logger.warn("makeTypification not yet implemented");
522 //success.setValue(false);
527 private void makePublicationStatus(TaxonNameBase name
, Element elPublicationStatus
, ResultWrapper
<Boolean
> success
){
530 if (elPublicationStatus
!= null){
531 //logger.warn("makePublicationStatus not yet implemented");
532 //success.setValue(false);
536 private void makeProviderLink(TaxonNameBase name
, Element elProviderLink
, ResultWrapper
<Boolean
> success
){
537 if (elProviderLink
!= null){
538 //logger.warn("makeProviderLink not yet implemented");
539 //success.setValue(false);
544 private void makeProviderSpecificData(TaxonNameBase name
, Element elProviderSpecificData
, ResultWrapper
<Boolean
> success
){
545 if (elProviderSpecificData
!= null){
546 //logger.warn("makeProviderSpecificData not yet implemented");
547 //success.setValue(false);
553 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)
555 protected boolean isIgnore(TcsXmlImportState state
){
556 return ! state
.getConfig().isDoTaxonNames();