2 * Copyright (C) 2008 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.
9 package eu
.etaxonomy
.cdm
.io
.excel
.distribution
;
11 import java
.io
.FileNotFoundException
;
13 import java
.util
.ArrayList
;
14 import java
.util
.HashMap
;
15 import java
.util
.List
;
19 import org
.apache
.log4j
.Logger
;
20 import org
.springframework
.stereotype
.Component
;
21 import org
.springframework
.transaction
.TransactionStatus
;
23 import eu
.etaxonomy
.cdm
.api
.service
.config
.IIdentifiableEntityServiceConfigurator
;
24 import eu
.etaxonomy
.cdm
.api
.service
.config
.impl
.IdentifiableServiceConfiguratorImpl
;
25 import eu
.etaxonomy
.cdm
.common
.CdmUtils
;
26 import eu
.etaxonomy
.cdm
.common
.ExcelUtils
;
27 import eu
.etaxonomy
.cdm
.io
.common
.CdmIoBase
;
28 import eu
.etaxonomy
.cdm
.io
.common
.ICdmIO
;
29 import eu
.etaxonomy
.cdm
.io
.common
.IImportConfigurator
;
30 import eu
.etaxonomy
.cdm
.io
.common
.MapWrapper
;
31 import eu
.etaxonomy
.cdm
.io
.excel
.common
.ExcelImportState
;
32 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
33 import eu
.etaxonomy
.cdm
.model
.description
.DescriptionElementBase
;
34 import eu
.etaxonomy
.cdm
.model
.description
.Distribution
;
35 import eu
.etaxonomy
.cdm
.model
.description
.PresenceAbsenceTermBase
;
36 import eu
.etaxonomy
.cdm
.model
.description
.PresenceTerm
;
37 import eu
.etaxonomy
.cdm
.model
.description
.TaxonDescription
;
38 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
39 import eu
.etaxonomy
.cdm
.model
.location
.TdwgArea
;
40 import eu
.etaxonomy
.cdm
.model
.name
.TaxonNameBase
;
41 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
42 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
45 * @author a.babadshanjan
50 public class DistributionImport
extends CdmIoBase
<ExcelImportState
> implements ICdmIO
<ExcelImportState
> {
53 private static final String EDIT_NAME_COLUMN
= "EDIT";
54 private static final String TDWG_DISTRIBUTION_COLUMN
= "TDWG";
55 private static final String STATUS_COLUMN
= "Status";
57 // private static final String LITERATURE_NUMBER_COLUMN = "Lit.";
58 // private static final String LITERATURE_COLUMN = "Literature";
59 // private static final String VERNACULAR_NAME_COLUMN = "Vernacular";
60 // private static final String HABITAT_COLUMN = "Habitat";
61 // private static final String CONTROL_COLUMN = "Control";
62 // private static final String TRANSLATED_COLUMN = "Translated";
63 // private static final String ISO_DISTRIBUTION_COLUMN = "ISO";
64 // private static final String NOTES_COLUMN = "Notes";
65 // private static final String PAGE_NUMBER_COLUMN = "Page";
66 // private static final String INFO_COLUMN = "Info";
68 private static final Logger logger
= Logger
.getLogger(DistributionImport
.class);
70 // Stores already processed descriptions
71 Map
<Taxon
, TaxonDescription
> myDescriptions
= new HashMap
<Taxon
, TaxonDescription
>();
74 protected boolean doInvoke(ExcelImportState state
) {
76 if (logger
.isDebugEnabled()) { logger
.debug("Importing distribution data"); }
78 // read and save all rows of the excel worksheet
79 ArrayList
<HashMap
<String
, String
>> recordList
;
80 URI source
= state
.getConfig().getSource();
82 recordList
= ExcelUtils
.parseXLS(source
);
83 } catch (FileNotFoundException e
) {
84 String message
= "File not found: " + source
;
85 warnProgress(state
, message
, e
);
86 logger
.error(message
);
89 if (recordList
!= null) {
90 HashMap
<String
,String
> record
= null;
91 TransactionStatus txStatus
= startTransaction();
93 for (int i
= 0; i
< recordList
.size(); i
++) {
94 record
= recordList
.get(i
);
95 analyzeRecord(record
);
97 commitTransaction(txStatus
);
101 if (logger
.isDebugEnabled()) { logger
.debug("End distribution data import"); }
103 } catch (Exception e
) {
104 logger
.error("Error closing the application context");
113 * Reads the data of one Excel sheet row
115 private void analyzeRecord(HashMap
<String
,String
> record
) {
120 * Status (only entries if not native)
125 String editName
= "";
126 ArrayList
<String
> distributionList
= new ArrayList
<String
>();
128 String literatureNumber
= "";
129 String literature
= "";
131 Set
<String
> keys
= record
.keySet();
133 for (String key
: keys
) {
135 String value
= (String
) record
.get(key
);
136 if (!value
.equals("")) {
137 if (logger
.isDebugEnabled()) { logger
.debug(key
+ ": '" + value
+ "'"); }
140 if (key
.contains(EDIT_NAME_COLUMN
)) {
141 editName
= (String
) CdmUtils
.removeDuplicateWhitespace(value
.trim());
143 } else if(key
.contains(TDWG_DISTRIBUTION_COLUMN
)) {
144 distributionList
= CdmUtils
.buildList(value
);
146 } else if(key
.contains(STATUS_COLUMN
)) {
147 status
= (String
) CdmUtils
.removeDuplicateWhitespace(value
.trim());
149 // } else if(key.contains(LITERATURE_NUMBER_COLUMN)) {
150 // literatureNumber = (String) CdmUtils.removeDuplicateWhitespace(value.trim());
152 // } else if(key.contains(LITERATURE_COLUMN)) {
153 // literature = (String) CdmUtils.removeDuplicateWhitespace(value.trim());
156 //logger.warn("Column " + key + " ignored");
160 // Store the data of this record in the DB
161 if (!editName
.equals("")) {
162 saveRecord(editName
, distributionList
, status
, literatureNumber
, literature
);
168 * Stores the data of one Excel sheet row in the database
170 private void saveRecord(String taxonName
, ArrayList
<String
> distributionList
,
171 String status
, String literatureNumber
, String literature
) {
173 IdentifiableServiceConfiguratorImpl config
=
174 IdentifiableServiceConfiguratorImpl
.NewInstance();
175 config
.setTitleSearchString(taxonName
);
176 config
.setMatchMode(MatchMode
.BEGINNING
);
179 // get the matching names from the DB
180 //List<TaxonNameBase> taxonNameBases = getNameService().findByTitle(config);
181 List
<TaxonNameBase
<?
,?
>> taxonNameBases
= getNameService().findNamesByTitle(taxonName
);
182 if (taxonNameBases
.isEmpty()) {
183 logger
.error("Taxon name '" + taxonName
+ "' not found in DB");
185 if (logger
.isDebugEnabled()) { logger
.debug("Taxon found"); }
188 // get the taxa for the matching names
189 for(TaxonNameBase
<?
,?
> dbTaxonName
: taxonNameBases
) {
191 Set
<Taxon
> taxa
= dbTaxonName
.getTaxa();
192 if (taxa
.isEmpty()) {
193 logger
.warn("No taxon found for name '" + taxonName
+ "'");
194 } else if (taxa
.size() > 1) {
195 logger
.warn("More than one taxa found for name '" + taxonName
+ "'");
198 for(Taxon taxon
: taxa
) {
200 TaxonDescription myDescription
= null;
202 // If we have created a description for this taxon earlier, take this one.
203 // Otherwise, create a new description.
204 // We don't update any existing descriptions in the database at this point.
205 if (myDescriptions
.containsKey(taxon
)) {
206 myDescription
= myDescriptions
.get(taxon
);
208 myDescription
= TaxonDescription
.NewInstance(taxon
);
209 taxon
.addDescription(myDescription
);
210 myDescriptions
.put(taxon
, myDescription
);
214 PresenceAbsenceTermBase
<?
> presenceAbsenceStatus
= PresenceTerm
.NewInstance();
215 if (status
.equals("")) {
216 presenceAbsenceStatus
= PresenceTerm
.NATIVE();
218 presenceAbsenceStatus
= PresenceTerm
.getPresenceTermByAbbreviation(status
);
220 // TODO: Handle absence case.
221 // This case has not yet occurred in the excel input file, though.
223 /* Set to true if taxon needs to be saved if at least one new distribution exists */
224 boolean save
= false;
227 for (String distribution
: distributionList
) {
229 /* Set to true if this distribution is a new one*/
230 boolean ignore
= false;
232 if(!distribution
.equals("")) {
233 NamedArea namedArea
= TdwgArea
.getAreaByTdwgAbbreviation(distribution
);
234 TaxonDescription taxonDescription
= myDescriptions
.get(taxon
);
235 if (namedArea
!= null) {
236 // Check against existing distributions and ignore the ones that occur multiple times
237 Set
<DescriptionElementBase
> myDescriptionElements
= taxonDescription
.getElements();
238 for(DescriptionElementBase descriptionElement
: myDescriptionElements
) {
239 if (descriptionElement
instanceof Distribution
) {
240 if (namedArea
== ((Distribution
)descriptionElement
).getArea()) {
242 if (logger
.isDebugEnabled()) {
243 logger
.debug("Distribution ignored: " + distribution
);
249 // Create new distribution if not yet exist
250 if (ignore
== false) {
252 Distribution newDistribution
= Distribution
.NewInstance(namedArea
, presenceAbsenceStatus
);
253 myDescription
.addElement(newDistribution
);
254 if (logger
.isDebugEnabled()) {
255 logger
.debug("Distribution created: " + newDistribution
.toString());
262 getTaxonService().save(taxon
);
263 if (logger
.isDebugEnabled()) { logger
.debug("Taxon saved"); }
267 } catch (Exception e
) {
268 logger
.error("Error");
275 protected boolean doCheck(ExcelImportState state
) {
276 boolean result
= true;
277 logger
.warn("No check implemented for distribution data import");
283 protected boolean isIgnore(ExcelImportState state
) {