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
.cyprus
;
12 import java
.util
.Arrays
;
13 import java
.util
.HashMap
;
14 import java
.util
.HashSet
;
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
.springframework
.stereotype
.Component
;
23 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
24 import eu
.etaxonomy
.cdm
.io
.excel
.common
.ExcelImporterBase
;
25 import eu
.etaxonomy
.cdm
.model
.common
.Language
;
26 import eu
.etaxonomy
.cdm
.model
.common
.Marker
;
27 import eu
.etaxonomy
.cdm
.model
.common
.MarkerType
;
28 import eu
.etaxonomy
.cdm
.model
.description
.Distribution
;
29 import eu
.etaxonomy
.cdm
.model
.description
.Feature
;
30 import eu
.etaxonomy
.cdm
.model
.description
.PresenceTerm
;
31 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
32 import eu
.etaxonomy
.cdm
.model
.description
.TextData
;
33 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
34 import eu
.etaxonomy
.cdm
.model
.location
.TdwgArea
;
35 import eu
.etaxonomy
.cdm
.model
.name
.BotanicalName
;
36 import eu
.etaxonomy
.cdm
.model
.name
.NomenclaturalCode
;
37 import eu
.etaxonomy
.cdm
.model
.name
.NonViralName
;
38 import eu
.etaxonomy
.cdm
.model
.name
.Rank
;
39 import eu
.etaxonomy
.cdm
.model
.reference
.Reference
;
40 import eu
.etaxonomy
.cdm
.model
.taxon
.Classification
;
41 import eu
.etaxonomy
.cdm
.model
.taxon
.Synonym
;
42 import eu
.etaxonomy
.cdm
.model
.taxon
.SynonymRelationshipType
;
43 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
44 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonBase
;
45 import eu
.etaxonomy
.cdm
.strategy
.parser
.INonViralNameParser
;
46 import eu
.etaxonomy
.cdm
.strategy
.parser
.NonViralNameParserImpl
;
49 * @author a.babadshanjan
55 public class CyprusExcelImport
extends ExcelImporterBase
<CyprusImportState
> {
56 private static final Logger logger
= Logger
.getLogger(CyprusExcelImport
.class);
58 public static Set
<String
> validMarkers
= new HashSet
<String
>(Arrays
.asList(new String
[]{"", "valid", "accepted", "a", "v", "t"}));
59 public static Set
<String
> synonymMarkers
= new HashSet
<String
>(Arrays
.asList(new String
[]{"", "invalid", "synonym", "s", "i"}));
63 protected boolean isIgnore(CyprusImportState state
) {
69 * @see eu.etaxonomy.cdm.io.common.CdmIoBase#doCheck(eu.etaxonomy.cdm.io.common.IoStateBase)
72 protected boolean doCheck(CyprusImportState state
) {
73 logger
.warn("DoCheck not yet implemented for CyprusExcelImport");
77 // protected static final String ID_COLUMN = "Id";
78 protected static final String SPECIES_COLUMN
= "species";
79 protected static final String SUBSPECIES_COLUMN
= "subspecies";
80 protected static final String GENUS_COLUMN
= "genus";
81 protected static final String FAMILY_COLUMN
= "family";
82 protected static final String DIVISION_COLUMN
= "division";
83 protected static final String HOMOTYPIC_SYNONYM_COLUMN
= "homotypic synonyms";
84 protected static final String HETEROTYPIC_SYNONYMS_COLUMN
= "heterotypic synonyms";
85 protected static final String ENDEMISM_COLUMN
= "endemism";
87 protected static final String STATUS_COLUMN
= "status";
88 protected static final String RED_DATA_BOOK_CATEGORY_COLUMN
= "red data book category";
89 protected static final String SYSTEMATICS_COLUMN
= "systematics";
93 // TODO: This enum is for future use (perhaps).
94 protected enum Columns
{
97 Subspecies("subspecies"),
100 Division("division"),
101 HomotypicSynonyms("homotypic synonyms"),
102 HeterotypicSynonyms("heterotypic synonyms"),
104 Endemism("endemism");
107 private String value
;
109 private Columns(String head
) {
113 public String
head() {
117 public String
value() {
124 protected boolean analyzeRecord(HashMap
<String
, String
> record
, CyprusImportState state
) {
126 boolean success
= true;
127 Set
<String
> keys
= record
.keySet();
129 CyprusRow cyprusRow
= new CyprusRow();
130 state
.setCyprusRow(cyprusRow
);
132 for (String originalKey
: keys
) {
134 String indexedKey
= CdmUtils
.removeDuplicateWhitespace(originalKey
.trim()).toString();
135 String
[] split
= indexedKey
.split("_");
136 String key
= split
[0];
137 if (split
.length
> 1){
138 String indexString
= split
[1];
140 index
= Integer
.valueOf(indexString
);
141 } catch (NumberFormatException e
) {
142 String message
= "Index must be integer";
143 logger
.error(message
);
148 String value
= (String
) record
.get(indexedKey
);
149 if (! StringUtils
.isBlank(value
)) {
150 if (logger
.isDebugEnabled()) { logger
.debug(key
+ ": " + value
); }
151 value
= CdmUtils
.removeDuplicateWhitespace(value
.trim()).toString();
157 if (key
.equalsIgnoreCase(SPECIES_COLUMN
)) {
158 // int ivalue = floatString2IntValue(value);
159 cyprusRow
.setSpecies(value
);
161 } else if(key
.equalsIgnoreCase(SUBSPECIES_COLUMN
)) {
162 cyprusRow
.setSubspecies(value
);
164 } else if(key
.equalsIgnoreCase(HOMOTYPIC_SYNONYM_COLUMN
)) {
165 cyprusRow
.setHomotypicSynonyms(value
);
167 } else if(key
.equalsIgnoreCase(HETEROTYPIC_SYNONYMS_COLUMN
)) {
168 cyprusRow
.setHeterotypicSynonyms(value
);
170 } else if(key
.equalsIgnoreCase(ENDEMISM_COLUMN
)) {
171 cyprusRow
.setEndemism(value
);
173 } else if(key
.equalsIgnoreCase(STATUS_COLUMN
)) {
174 cyprusRow
.setStatus(value
);
176 } else if(key
.equalsIgnoreCase(RED_DATA_BOOK_CATEGORY_COLUMN
)) {
177 cyprusRow
.setRedDataBookCategory(value
);
179 } else if(key
.equalsIgnoreCase(SYSTEMATICS_COLUMN
)) {
180 cyprusRow
.setSystematics(value
);
182 } else if(key
.equalsIgnoreCase(GENUS_COLUMN
)) {
183 cyprusRow
.setGenus(value
);
185 } else if(key
.equalsIgnoreCase(FAMILY_COLUMN
)) {
186 cyprusRow
.setFamily(value
);
188 } else if(key
.equalsIgnoreCase(DIVISION_COLUMN
)) {
189 cyprusRow
.setDivision(value
);
193 logger
.error("Unexpected column header " + key
);
199 private static INonViralNameParser nameParser
= NonViralNameParserImpl
.NewInstance();
200 private static NomenclaturalCode nc
= NomenclaturalCode
.ICBN
;
201 private Feature redBookCategory
;
202 private PresenceTerm indigenous
;
203 private PresenceTerm casual
;
204 private PresenceTerm nonInvasive
;
205 private PresenceTerm invasive
;
206 private PresenceTerm questionable
;
208 private void makeTerms(CyprusImportState state
) {
210 UUID redBookUuid
= UUID
.fromString("df59d44a-ee5a-4c01-8637-127cc804842d");
211 redBookCategory
= this.getFeature(state
, redBookUuid
, "Red book category", "Red data book category", "Red book");
212 getTermService().save(redBookCategory
);
214 UUID indigenousUuid
= UUID
.fromString("b325859b-504b-45e0-9ef0-d5c1602fcc0f");
215 indigenous
= this.getPresenceTerm(state
, indigenousUuid
, "Indigenous", "Indigenous", "IN");
216 getTermService().save(indigenous
);
218 UUID casualUuid
= UUID
.fromString("5e81353c-38a3-4ca6-b979-0d9abc93b877");
219 casual
= this.getPresenceTerm(state
, casualUuid
, "Casual", "Casual", "CA");
220 getTermService().save(redBookCategory
);
222 UUID nonInvasiveUuid
= UUID
.fromString("1b025e8b-901a-42e8-9739-119b410c6f03");
223 nonInvasive
= this.getPresenceTerm(state
, nonInvasiveUuid
, "Naturalized non-invasive", "Naturalized non-invasive", "NN");
224 getTermService().save(nonInvasive
);
226 UUID invasiveUuid
= UUID
.fromString("faf2d271-868a-4bf7-b0b8-a1c5ab309de2");
227 invasive
= this.getPresenceTerm(state
, invasiveUuid
, "Naturalized invasive", "Naturalized invasive", "NA");
228 getTermService().save(invasive
);
231 UUID questionableUuid
= UUID
.fromString("4b48f675-a6cf-49f3-a5ba-77e2c2979eb3");
232 questionable
= this.getPresenceTerm(state
, questionableUuid
, "Questionable", "Questionable", "Q");
233 getTermService().save(questionable
);
236 // UUID redBookUuid = UUID.fromString("d8416d46-b5b4-45d5-b26b-9bda4fa491c9");
237 // term = this.getPresenceTerm(state, redBookUuid, "Red book category", "Red data book category", "Red book");
238 // getTermService().save(term);
240 // UUID redBookUuid = UUID.fromString("813a58bd-f8ab-4a80-9029-87a112dbb59f");
241 // term = this.getPresenceTerm(state, redBookUuid, "Red book category", "Red data book category", "Red book");
242 // getTermService().save(term);
246 // PresenceTerm status = null;
247 // }else if (statusString.contains("Cultivated")){
248 // status = PresenceTerm.CULTIVATED();
249 // }else if (statusString.contains("non-invasive")){
251 // status = PresenceTerm.NATURALISED();
252 // }else if (statusString.contains("invasive")){
254 // status = PresenceTerm.NATURALISED();
258 * Stores taxa records in DB
261 protected boolean firstPass(CyprusImportState state
) {
262 boolean success
= true;
264 CyprusRow taxonLight
= state
.getCyprusRow();
265 Reference citation
= null;
266 String microCitation
= null;
269 String speciesStr
= taxonLight
.getSpecies();
270 String subSpeciesStr
= taxonLight
.getSubspecies();
271 String homotypicSynonymsString
= taxonLight
.getHomotypicSynonyms();
272 List
<String
> homotypicSynonymList
= Arrays
.asList(homotypicSynonymsString
.split(";"));
273 String heterotypicSynonymsString
= taxonLight
.getHeterotypicSynonyms();
274 List
<String
> heterotypicSynonymList
= Arrays
.asList(heterotypicSynonymsString
.split(";"));
276 String systematicsString
= taxonLight
.getSystematics();
277 String endemismString
= taxonLight
.getEndemism();
278 String statusString
= taxonLight
.getStatus();
279 String redBookCategory
= taxonLight
.getRedDataBookCategory();
281 // BotanicalName subSpeciesName = (BotanicalName)nameParser.parseSimpleName(subSpeciesStr, nc, Rank.SUBSPECIES());
282 // BotanicalName speciesName = (BotanicalName)nameParser.parseSimpleName(speciesStr, nc, Rank.SPECIES());
284 // Classification classification = null;
286 if (StringUtils
.isNotBlank(speciesStr
)) {
287 Taxon mainTaxon
= null;
288 Taxon speciesTaxon
= (Taxon
)createTaxon(state
, Rank
.SPECIES(), speciesStr
, Taxon
.class, nc
);
289 mainTaxon
= speciesTaxon
;
290 if (StringUtils
.isNotBlank(subSpeciesStr
)){
291 Taxon subSpeciesTaxon
= (Taxon
)createTaxon(state
, Rank
.SUBSPECIES(), subSpeciesStr
, Taxon
.class, nc
);
293 if (subSpeciesTaxon
!= null){
294 makeParent(state
, speciesTaxon
, subSpeciesTaxon
, citation
, microCitation
);
296 mainTaxon
= subSpeciesTaxon
;
299 makeHigherTaxa(state
, taxonLight
, speciesTaxon
, citation
, microCitation
);
300 makeHomotypicSynonyms(state
, citation
, microCitation
, homotypicSynonymList
, mainTaxon
);
301 makeHeterotypicSynonyms(state
, citation
, microCitation
, heterotypicSynonymList
, mainTaxon
);
302 makeSystematics(systematicsString
, mainTaxon
);
303 makeEndemism(endemismString
, mainTaxon
);
304 makeStatus(statusString
, mainTaxon
);
305 makeRedBookCategory(redBookCategory
, mainTaxon
);
307 // state.putHigherTaxon(higherName, uuid);//(speciesStr, mainTaxon);
308 getTaxonService().save(mainTaxon
);
314 private void makeHigherTaxa(CyprusImportState state
, CyprusRow taxonLight
, Taxon speciesTaxon
, Reference citation
, String microCitation
) {
315 String divisionStr
= taxonLight
.getDivision();
316 String genusStr
= taxonLight
.getGenus();
317 String familyStr
= taxonLight
.getFamily();
319 Taxon division
= getTaxon(state
, divisionStr
, Rank
.DIVISION(), null, citation
, microCitation
);
320 Taxon family
= getTaxon(state
, familyStr
, Rank
.FAMILY(), division
, citation
, microCitation
);
321 Taxon genus
= getTaxon(state
, genusStr
, Rank
.GENUS(), family
, citation
, microCitation
);
322 makeParent(state
, genus
, speciesTaxon
, citation
, microCitation
) ;
326 private Taxon
getTaxon(CyprusImportState state
, String taxonNameStr
, Rank rank
, Taxon parent
, Reference citation
, String microCitation
) {
328 if (state
.containsHigherTaxon(taxonNameStr
)){
329 result
= state
.getHigherTaxon(taxonNameStr
);
331 result
= (Taxon
)createTaxon(state
, rank
, taxonNameStr
, Taxon
.class, nc
);
332 state
.putHigherTaxon(taxonNameStr
, result
);
334 makeParent(state
, null,result
, citation
, microCitation
);
336 makeParent(state
, parent
, result
, citation
, microCitation
);
344 private void makeHomotypicSynonyms(CyprusImportState state
,
345 Reference citation
, String microCitation
, List
<String
> homotypicSynonymList
, Taxon mainTaxon
) {
346 for (String homotypicSynonym
: homotypicSynonymList
){
347 if (StringUtils
.isNotBlank(homotypicSynonym
)){
348 Synonym synonym
= (Synonym
)createTaxon(state
, null, homotypicSynonym
, Synonym
.class, nc
);
349 mainTaxon
.addHomotypicSynonym(synonym
, citation
, microCitation
);
355 private void makeHeterotypicSynonyms(CyprusImportState state
, Reference citation
, String microCitation
, List
<String
> heterotypicSynonymList
, Taxon mainTaxon
) {
356 for (String heterotypicSynonym
: heterotypicSynonymList
){
357 if (StringUtils
.isNotBlank(heterotypicSynonym
)){
358 Synonym synonym
= (Synonym
)createTaxon(state
, null, heterotypicSynonym
, Synonym
.class, nc
);
359 mainTaxon
.addSynonym(synonym
, SynonymRelationshipType
.HETEROTYPIC_SYNONYM_OF(), citation
, microCitation
);
365 private void makeSystematics(String systematicsString
, Taxon mainTaxon
) {
367 if (StringUtils
.isNotBlank(systematicsString
)){
368 TaxonDescription td
= this.getTaxonDescription(mainTaxon
, false, true);
370 TextData textData
= TextData
.NewInstance(Feature
.SYSTEMATICS());
371 textData
.putText(systematicsString
, Language
.UNDETERMINED());
372 td
.addElement(textData
);
377 private void makeEndemism(String endemismString
, Taxon mainTaxon
) {
379 if (StringUtils
.isNotBlank(endemismString
)){
381 if (endemismString
.trim().equalsIgnoreCase("not endemic") || endemismString
.trim().equalsIgnoreCase("ne?")){
383 }else if (endemismString
.trim().equalsIgnoreCase("endemic")){
386 throw new RuntimeException(endemismString
+ " is not a valid value for endemism");
389 Marker marker
= Marker
.NewInstance(MarkerType
.ENDEMIC(), flag
);
390 mainTaxon
.addMarker(marker
);
395 private void makeStatus(String statusString
, Taxon mainTaxon
) {
398 if (StringUtils
.isNotBlank(statusString
)){
399 PresenceTerm status
= null;
400 if (statusString
.contains("Indigenous")){
402 }else if (statusString
.contains("Casual") || statusString
.contains("Causal")){
404 }else if (statusString
.contains("Cultivated")){
405 status
= PresenceTerm
.CULTIVATED();
406 }else if (statusString
.contains("non-invasive")){
407 status
= nonInvasive
;
408 }else if (statusString
.contains("invasive")){
410 }else if (statusString
.contains("Questionable")){
411 // status = PresenceTerm.NATIVE_PRESENCE_QUESTIONABLE();
412 status
= questionable
;
413 }else if (statusString
.startsWith("F")){
415 status
= PresenceTerm
.NATIVE_PRESENCE_QUESTIONABLE();
416 }else if (statusString
.equals("##")){
418 status
= PresenceTerm
.NATIVE_PRESENCE_QUESTIONABLE();
420 logger
.warn("Unknown status: " + statusString
);
421 status
= PresenceTerm
.PRESENT();
423 TaxonDescription td
= this.getTaxonDescription(mainTaxon
, false, true);
424 NamedArea area
= TdwgArea
.getAreaByTdwgAbbreviation("CYP");
425 Distribution distribution
= Distribution
.NewInstance(area
, status
);
426 td
.addElement(distribution
);
430 TextData textData
= TextData
.NewInstance(Feature
.STATUS());
431 textData
.putText(statusString
, Language
.ENGLISH());
432 td
.addElement(textData
);
437 private void makeRedBookCategory(String redBookCategory
, Taxon mainTaxon
) {
438 //red data book category
439 if (StringUtils
.isNotBlank(redBookCategory
)){
440 TaxonDescription td
= this.getTaxonDescription(mainTaxon
, false, true);
442 TextData textData
= TextData
.NewInstance(this.redBookCategory
);
443 textData
.putText(redBookCategory
, Language
.ENGLISH());
444 td
.addElement(textData
);
452 * Stores parent-child, synonym and common name relationships
455 protected boolean secondPass(CyprusImportState state
) {
456 boolean success
= true;
457 // CyprusRow cyprusRow = state.getCyprusRow();
467 * @param taxonNameStr
473 private TaxonBase
createTaxon(CyprusImportState state
, Rank rank
, String taxonNameStr
,
474 Class statusClass
, NomenclaturalCode nc
) {
476 NonViralName taxonNameBase
= null;
477 if (nc
== NomenclaturalCode
.ICVCN
){
478 logger
.warn("ICVCN not yet supported");
481 taxonNameBase
=(NonViralName
) nc
.getNewTaxonNameInstance(rank
);
482 //NonViralName nonViralName = (NonViralName)taxonNameBase;
483 INonViralNameParser parser
= nameParser
;//NonViralNameParserImpl.NewInstance();
484 taxonNameBase
= (NonViralName
<BotanicalName
>)parser
.parseFullName(taxonNameStr
, nc
, rank
);
486 //taxonNameBase.setNameCache(taxonNameStr);
491 Reference sec
= state
.getConfig().getSourceReference();
493 if (statusClass
.equals(Taxon
.class)){
494 taxonBase
= Taxon
.NewInstance(taxonNameBase
, sec
);
495 }else if (statusClass
.equals(Synonym
.class)){
496 taxonBase
= Synonym
.NewInstance(taxonNameBase
, sec
);
498 Taxon taxon
= Taxon
.NewInstance(taxonNameBase
, sec
);
499 taxon
.setTaxonStatusUnknown(true);
505 private boolean makeParent(CyprusImportState state
, Taxon parentTaxon
, Taxon childTaxon
, Reference citation
, String microCitation
){
506 boolean success
= true;
507 Reference sec
= state
.getConfig().getSourceReference();
509 // Reference sec = parentTaxon.getSec();
510 Classification tree
= state
.getTree(sec
);
512 tree
= makeTree(state
, sec
);
513 tree
.setTitleCache("Cyprus");
515 if (sec
.equals(childTaxon
.getSec())){
516 success
&= (null != tree
.addParentChild(parentTaxon
, childTaxon
, citation
, microCitation
));
518 logger
.warn("No relationship added for child " + childTaxon
.getTitleCache());