First version of Mexico import #5822
authorAndreas Müller <a.mueller@bgbm.org>
Fri, 17 Jun 2016 21:43:48 +0000 (23:43 +0200)
committerAndreas Müller <a.mueller@bgbm.org>
Fri, 17 Jun 2016 21:47:26 +0000 (23:47 +0200)
14 files changed:
app-import/src/main/java/eu/etaxonomy/cdm/app/common/CdmDestinations.java
app-import/src/main/java/eu/etaxonomy/cdm/app/mexico/MexicoBorhidiActivator.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/app/mexico/MexicoConabioActivator.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiExcelImport.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiImportConfigurator.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiTransformer.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioCommonNamesImport.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioDistributionImport.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioImportConfigurator.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioImportState.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioTaxonImport.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioTransformer.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/SimpleExcelTaxonImport.java [new file with mode: 0644]
app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/SimpleExcelTaxonImportState.java [new file with mode: 0644]

index d271519277859b906be2f78f59a6d8e93762fc35..c7742dc204364f6dc58a1b33cbdbeb8ddd59bc9a 100644 (file)
@@ -193,14 +193,6 @@ public class CdmDestinations {
                return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
        }
 
-       public static ICdmDataSource cdm_pesi_euromed(){
-               DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
-               String cdmServer = "160.45.63.175";
-               String cdmDB = "cdm_pesi_euromed";
-               String cdmUserName = "edit";
-               return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
-       }
-
        public static ICdmDataSource cdm_corvidae_dev(){
                DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
                String cdmServer = "160.45.63.175";
@@ -267,13 +259,21 @@ public class CdmDestinations {
                return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
        }
 
-          public static ICdmDataSource cdm_cuba_production(){
-               DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
-               String cdmServer = "160.45.63.171";
-               String cdmDB = "cdm_production_flora_cuba";
-               String cdmUserName = "edit";
-               return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
-           }
+    public static ICdmDataSource cdm_cuba_production(){
+        DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
+        String cdmServer = "160.45.63.171";
+        String cdmDB = "cdm_production_flora_cuba";
+        String cdmUserName = "edit";
+        return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
+    }
+
+    public static ICdmDataSource cdm_mexico_rubiaceae_production(){
+        DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
+        String cdmServer = "160.45.63.171";
+        String cdmDB = "cdm_production_rubiaceae_mexico";
+        String cdmUserName = "edit";
+        return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
+    }
 
        public static ICdmDataSource cdm_cyprus_production_tunnel(){
                DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
@@ -301,22 +301,6 @@ public class CdmDestinations {
                return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
        }
 
-       public static ICdmDataSource cdm_flora_malesiana_preview(){
-               DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
-               String cdmServer = "160.45.63.175";
-               String cdmDB = "cdm_edit_flora_malesiana";
-               String cdmUserName = "edit";
-               return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
-       }
-
-       public static ICdmDataSource cdm_flora_malesiana_production(){
-               DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
-               String cdmServer = "160.45.63.171";
-               String cdmDB = "cdm_production_flora_malesiana";
-               String cdmUserName = "edit";
-               return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
-       }
-
        public static ICdmDataSource cdm_portal_test_localhost(){
                DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
                String cdmServer = "127.0.0.1";
@@ -399,14 +383,6 @@ public class CdmDestinations {
                return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
        }
 
-       public static ICdmDataSource cdm_local_tdwg2010(){
-               DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
-               String cdmServer = "127.0.0.1";
-               String cdmDB = "cdm_tdwg2010";
-               String cdmUserName = "edit";
-               return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
-       }
-
 
        public static ICdmDataSource NULL(){
                return null;
@@ -519,7 +495,7 @@ public class CdmDestinations {
                String cdmUserName = "edit";
                return makeDestination(dbType, cdmServer, cdmDB, -1, cdmUserName, null);
        }
-       
+
        public static ICdmDataSource cdm_production_redlist_gefaesspflanzen(){
                DatabaseTypeEnum dbType = DatabaseTypeEnum.MySQL;
                String cdmServer = "160.45.63.171";
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/app/mexico/MexicoBorhidiActivator.java b/app-import/src/main/java/eu/etaxonomy/cdm/app/mexico/MexicoBorhidiActivator.java
new file mode 100644 (file)
index 0000000..e7d05f1
--- /dev/null
@@ -0,0 +1,133 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.app.mexico;
+
+import java.net.URI;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.app.common.CdmDestinations;
+import eu.etaxonomy.cdm.database.DbSchemaValidation;
+import eu.etaxonomy.cdm.database.ICdmDataSource;
+import eu.etaxonomy.cdm.io.common.CdmDefaultImport;
+import eu.etaxonomy.cdm.io.common.IImportConfigurator.CHECK;
+import eu.etaxonomy.cdm.io.mexico.MexicoBorhidiImportConfigurator;
+import eu.etaxonomy.cdm.model.agent.Person;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
+
+/**
+ * Activator for import of Borhidi Rubiaceae (Mexico)
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoBorhidiActivator {
+    private static final Logger logger = Logger.getLogger(MexicoBorhidiActivator.class);
+
+    //database validation status (create, update, validate ...)
+    static DbSchemaValidation hbm2dll = DbSchemaValidation.CREATE;
+
+    static final ICdmDataSource cdmDestination = CdmDestinations.localH2();
+//  static final ICdmDataSource cdmDestination = CdmDestinations.cdm_test_local_mysql_test();
+//    static final ICdmDataSource cdmDestination = CdmDestinations.cdm_mexico_rubiaceae_production();
+
+    static boolean invers = true;
+
+//    boolean doRubiaceae = include;
+
+//    static boolean include = !invers;
+
+
+    //feature tree uuid
+    public static final UUID featureTreeUuid = UUID.fromString("d1f4ed29-9aae-4f6e-aa1e-4a3bf780e11d");
+
+    //classification
+    static final UUID classificationUuid = UUID.fromString("8ebb2076-d849-47e0-ad32-4fe08ca61cac");
+    private static final String classificationName = "Rubiaceae Borhidi";
+
+    static final String sourceReferenceTitle = "Rubiáceas de México";
+
+    //check - import
+    static final CHECK check = CHECK.IMPORT_WITHOUT_CHECK;
+
+    boolean doVocabularies = (hbm2dll == DbSchemaValidation.CREATE);
+//    static final boolean doTaxa = false;
+//    static final boolean doDeduplicate = true;
+
+    private void doImport(ICdmDataSource cdmDestination){
+
+        URI source = borhidi();
+
+        //make Source
+        MexicoBorhidiImportConfigurator config= MexicoBorhidiImportConfigurator.NewInstance(source, cdmDestination);
+        config.setClassificationUuid(classificationUuid);
+        config.setClassificationName(classificationName);
+        config.setCheck(check);
+//        config.setDoTaxa(doTaxa);
+        config.setDbSchemaValidation(hbm2dll);
+        config.setSourceReferenceTitle(sourceReferenceTitle);
+//        config.setDoVocabularies(doVocabularies);
+
+        config.setSource(source);
+        String fileName = source.toString();
+        fileName = fileName.substring(fileName.lastIndexOf("/") + 1 );
+
+        String message = "Start import from ("+ fileName + ") ...";
+        System.out.println(message);
+        logger.warn(message);
+
+        config.setSourceReference(getSourceReference(sourceReferenceTitle));
+//        config.setDoVocabularies(doVocabularies);
+
+        CdmDefaultImport<MexicoBorhidiImportConfigurator> myImport = new CdmDefaultImport<MexicoBorhidiImportConfigurator>();
+
+        myImport.invoke(config);
+
+//        if (makeFeatureTree){
+//            FeatureTree tree = makeFeatureNodes(myImport.getCdmAppController().getTermService());
+//            myImport.getCdmAppController().getFeatureTreeService().saveOrUpdate(tree);
+//        }
+
+        System.out.println("End import from ("+ source.toString() + ")...");
+
+    }
+
+
+    //Borhidi
+    public static URI borhidi() {
+        return URI.create("file:////BGBM-PESIHPC/Mexico/Borhidi_2012.xlsx");
+    }
+
+    private Reference getSourceReference(@SuppressWarnings("unused") String string) {
+        Reference result = ReferenceFactory.newBook();
+//        result.setTitleCache(string, true);
+        result.setTitle("Rubiáceas de México");
+        result.setPlacePublished("Budapest");
+        result.setPublisher("Akadémiai Kiadó");
+        result.setPages("512 pp.");
+        result.setDatePublished(TimePeriodParser.parseString("2006"));
+        Person borhidi = Person.NewTitledInstance("Borhidi");
+        borhidi.setFirstname("Attila");
+        result.setAuthorship(borhidi);
+        return result;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        MexicoBorhidiActivator me = new MexicoBorhidiActivator();
+        me.doImport(cdmDestination);
+        System.exit(0);
+    }
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/app/mexico/MexicoConabioActivator.java b/app-import/src/main/java/eu/etaxonomy/cdm/app/mexico/MexicoConabioActivator.java
new file mode 100644 (file)
index 0000000..12d026e
--- /dev/null
@@ -0,0 +1,128 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.app.mexico;
+
+import java.net.URI;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.app.common.CdmDestinations;
+import eu.etaxonomy.cdm.database.DbSchemaValidation;
+import eu.etaxonomy.cdm.database.ICdmDataSource;
+import eu.etaxonomy.cdm.io.common.CdmDefaultImport;
+import eu.etaxonomy.cdm.io.common.IImportConfigurator.CHECK;
+import eu.etaxonomy.cdm.io.mexico.MexicoConabioImportConfigurator;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoConabioActivator {
+    private static final Logger logger = Logger.getLogger(MexicoConabioActivator.class);
+
+    //database validation status (create, update, validate ...)
+    static DbSchemaValidation hbm2dll = DbSchemaValidation.VALIDATE;
+
+//    static final ICdmDataSource cdmDestination = CdmDestinations.localH2();
+  static final ICdmDataSource cdmDestination = CdmDestinations.cdm_test_local_mysql_test();
+//    static final ICdmDataSource cdmDestination = CdmDestinations.cdm_mexico_production();
+
+    static boolean invers = true;
+
+//    boolean doRubiaceae = include;
+
+//    static boolean include = !invers;
+
+
+    //feature tree uuid
+    public static final UUID featureTreeUuid = UUID.fromString("d1f4ed29-9aae-4f6e-aa1e-4a3bf780e11d");
+
+    //classification
+    static final UUID classificationUuid = UUID.fromString("61968b43-e881-4043-b5c2-ba192e8f72dc");
+    private static final String classificationName = "Rubiaceae Conabio";
+
+    static final String sourceReferenceTitle = "Conabio XXX";
+
+    //check - import
+    static final CHECK check = CHECK.IMPORT_WITHOUT_CHECK;
+
+    boolean doVocabularies = (hbm2dll == DbSchemaValidation.CREATE);
+    static final boolean doTaxa = true;
+    static final boolean doDistributions = false;
+    static final boolean doCommonNames = false;
+//    static final boolean doDeduplicate = true;
+
+    private void doImport(ICdmDataSource cdmDestination){
+
+        URI source = conabio_rubiaceae();
+
+        //make Source
+        MexicoConabioImportConfigurator config= MexicoConabioImportConfigurator.NewInstance(source, cdmDestination);
+        config.setClassificationUuid(classificationUuid);
+        config.setClassificationName(classificationName);
+        config.setCheck(check);
+        config.setDoTaxa(doTaxa);
+        config.setDoDistributions(doDistributions);
+        config.setDoCommonNames(doCommonNames);
+        config.setDbSchemaValidation(hbm2dll);
+        config.setSourceReferenceTitle(sourceReferenceTitle);
+//        config.setDoVocabularies(doVocabularies);
+
+        config.setSource(source);
+        String fileName = source.toString();
+        fileName = fileName.substring(fileName.lastIndexOf("/") + 1 );
+
+        String message = "Start import from ("+ fileName + ") ...";
+        System.out.println(message);
+        logger.warn(message);
+
+        config.setSourceReference(getSourceReference(sourceReferenceTitle));
+//        config.setDoVocabularies(doVocabularies);
+
+        CdmDefaultImport<MexicoConabioImportConfigurator> myImport = new CdmDefaultImport<MexicoConabioImportConfigurator>();
+
+        myImport.invoke(config);
+
+//        if (makeFeatureTree){
+//            FeatureTree tree = makeFeatureNodes(myImport.getCdmAppController().getTermService());
+//            myImport.getCdmAppController().getFeatureTreeService().saveOrUpdate(tree);
+//        }
+
+        System.out.println("End import from ("+ source.toString() + ")...");
+
+    }
+
+
+    //Conabio Rubiaceae
+    public static URI conabio_rubiaceae() {
+        return URI.create("file:////BGBM-PESIHPC/Mexico/CONABIO-Rubiaceae.xlsx");
+    }
+
+    private Reference getSourceReference(String string) {
+        Reference result = ReferenceFactory.newGeneric();
+        result.setTitleCache(string, true);
+//        result.setInReference(inRef);
+//        inRef.setTitleCache(sourceReferenceTitle, true);
+        return result;
+    }
+
+    /**
+     * @param args
+     */
+    public static void main(String[] args) {
+        MexicoConabioActivator me = new MexicoConabioActivator();
+        me.doImport(cdmDestination);
+        System.exit(0);
+    }
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiExcelImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiExcelImport.java
new file mode 100644 (file)
index 0000000..331ad01
--- /dev/null
@@ -0,0 +1,265 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.model.common.DefinedTerm;
+import eu.etaxonomy.cdm.model.common.Extension;
+import eu.etaxonomy.cdm.model.common.ExtensionType;
+import eu.etaxonomy.cdm.model.common.Identifier;
+import eu.etaxonomy.cdm.model.common.TermVocabulary;
+import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
+import eu.etaxonomy.cdm.model.description.Feature;
+import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
+import eu.etaxonomy.cdm.model.description.TextData;
+import eu.etaxonomy.cdm.model.media.Media;
+import eu.etaxonomy.cdm.model.name.BotanicalName;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+import eu.etaxonomy.cdm.model.name.Rank;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+@Component
+public class MexicoBorhidiExcelImport<CONFIG extends MexicoBorhidiImportConfigurator>
+        extends SimpleExcelTaxonImport<CONFIG>{
+    private static final Logger logger = Logger.getLogger(MexicoBorhidiExcelImport.class);
+    private static final long serialVersionUID = -3607776356577606657L;
+
+    private  static List<String> expectedKeys= Arrays.asList(new String[]{
+            "FullnameNoAuthors","OutputNameID","OutputFullNameWithAuthors"
+            ,"OutputAbbreviatedTitle","OutputCollation","OutputVolume",
+            "OutputIssue","OutputPage","OutputTitlePageYear","OutputYearPublished",
+            "OutputBHLLink"});
+
+
+    @Override
+    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
+        String line = state.getCurrentLine() + ": ";
+        HashMap<String, String> record = state.getOriginalRecord();
+
+        Set<String> keys = record.keySet();
+        checkAllKeysExist(line, keys, expectedKeys);
+
+        if (record.get("FullnameNoAuthors") == null ){
+            logger.warn("No FullnameNoAuthors given: " + line);
+            return;
+        }
+
+        //Name
+        BotanicalName speciesName = makeName(record, state);
+
+        //Taxon
+        Reference sec = state.getConfig().getSourceReference();
+        Taxon taxon = Taxon.NewInstance(speciesName, sec);
+        TaxonNode rubiaceae = getHighestNode(state);
+//        rubiaceae.addChildTaxon(taxon, null, null);
+
+        //make genus
+        makeGenus(state, speciesName, sec, taxon, rubiaceae);
+
+        //add tropicos identifier
+        String tropicosId = record.get("OutputNameID");
+        if (isNotBlank(tropicosId)){
+            String tropicosIdTypeLabel = "Tropicos Name Identifier";
+            UUID uuid = MexicoBorhidiTransformer.uuidTropicosNameIdentifier;
+            TermVocabulary<DefinedTerm> voc = null;  //for now it goes to user defined voc
+            DefinedTerm identifierType = this.getIdentiferType(state, uuid, tropicosIdTypeLabel, tropicosIdTypeLabel, null, voc);
+            Identifier<Taxon> identifier = Identifier.NewInstance(tropicosId, identifierType);
+            taxon.addIdentifier(identifier);
+        }
+
+    }
+
+
+    private Classification classification;
+    private TaxonNode rubiaceaeNode;
+    /**
+     * @return
+     */
+    private TaxonNode getHighestNode(SimpleExcelTaxonImportState<CONFIG> state) {
+        if (rubiaceaeNode == null){
+            MexicoBorhidiImportConfigurator config = state.getConfig();
+            classification = Classification.NewInstance(state.getConfig().getClassificationName());
+            classification.setUuid(config.getClassificationUuid());
+            classification.setReference(config.getSourceReference());
+            BotanicalName nameRubiaceae = BotanicalName.NewInstance(Rank.FAMILY());
+            nameRubiaceae.setGenusOrUninomial("Rubiaceae");
+            Taxon rubiaceaeTaxon = Taxon.NewInstance(nameRubiaceae, classification.getReference());
+            rubiaceaeNode = classification.addChildTaxon(rubiaceaeTaxon, null, null);
+            getClassificationService().save(classification);
+        }
+        return rubiaceaeNode;
+    }
+
+    /**
+     * @param record
+     * @param state
+     * @return
+     */
+    private BotanicalName makeName(HashMap<String, String> record, SimpleExcelTaxonImportState<CONFIG> state) {
+        String line = state.getCurrentLine() + ": ";
+
+        String fullNameStr = getValue(record, "OutputFullNameWithAuthors");
+        String volume = getValue(record, "OutputVolume");
+        String issue = getValue(record, "OutputIssue");
+        String page = getValue(record, "OutputPage");
+        String titleYear = getValue(record, "OutputTitlePageYear");
+        String publishedYear = getValue(record, "OutputYearPublished");
+        String refAbbrevTitle = getValue(record, "OutputAbbreviatedTitle");
+        String outputCollation = getValue(record, "OutputCollation");
+
+        BotanicalName name = (BotanicalName)nameParser.parseFullName(fullNameStr, NomenclaturalCode.ICNAFP, Rank.SPECIES());
+        if (name.isProtectedTitleCache()){
+            logger.warn(line + "Name could not be parsed: " + fullNameStr );
+        }else{
+            replaceAuthorNames(state, name);
+        }
+
+        String[] volumeDetail = makeVolumeDetail(outputCollation);
+
+        if (refAbbrevTitle != null){
+            if (volume != null){
+                Reference journal = state.getReference(refAbbrevTitle);
+                if (journal == null){
+                    journal = ReferenceFactory.newJournal();
+                    journal.setAbbrevTitle(refAbbrevTitle);
+                    state.putReference(refAbbrevTitle, journal);
+                }
+                Reference article = ReferenceFactory.newArticle();
+
+                //volume + issue
+    //            if (isNotBlank(issue)){
+    //                volume = volume + "(" + issue + ")";
+    //            }
+                volume = volumeDetail[0];
+                String detail = volumeDetail.length > 1 ? volumeDetail[1] : null;
+
+                //            String detail = page;
+                name.setNomenclaturalMicroReference(detail);
+
+                article.setVolume(CdmUtils.Ne(volume));
+                article.setInReference(journal);
+
+                titleYear = (isBlank(publishedYear)? titleYear : "\"" + titleYear + "\"[" + publishedYear + "]");
+                article.setDatePublished(TimePeriodParser.parseString(titleYear));
+
+                Reference existingArticle = state.getReference(article.getTitleCache());
+                if (existingArticle != null){
+                    name.setNomenclaturalReference(existingArticle);
+                }else{
+                    name.setNomenclaturalReference(article);
+                    state.putReference(article.getTitleCache(), article);
+                }
+            }else{
+
+                Reference book = ReferenceFactory.newBook();
+                book.setAbbrevTitle(refAbbrevTitle);
+
+                if (volumeDetail.length > 1){
+                    logger.warn(line + "Book outputCollation has volume part");
+                }
+
+                //year
+                titleYear = (isBlank(publishedYear)? titleYear : "\"" + titleYear + "\"[" + publishedYear + "]");
+                book.setDatePublished(TimePeriodParser.parseString(titleYear));
+
+                //deduplicate
+                Reference existingBook = state.getReference(book.getTitleCache());
+                if (existingBook != null){
+                    name.setNomenclaturalReference(existingBook);
+                }else{
+                    name.setNomenclaturalReference(book);
+                    state.putReference(book.getTitleCache(), book);
+                }
+
+                //micro ref
+                String detail = outputCollation;
+                //String detail = page;
+                name.setNomenclaturalMicroReference(detail);
+            }
+        }
+
+        addNomRefExtension(state, name);
+
+
+        //add protologue
+        String bhlLink = record.get("OutputBHLLink");
+        if (isNotBlank(bhlLink)){
+            URI uri;
+            try {
+                uri = new URI(bhlLink);
+                Media media = Media.NewInstance(uri, null, null, null);
+                TaxonNameDescription desc = TaxonNameDescription.NewInstance(name);
+                desc.setTitleCache("Protologue for " + name.getNameCache(), true);
+                DescriptionElementBase elem = TextData.NewInstance(Feature.PROTOLOGUE());
+                elem.addMedia(media);
+                desc.addElement(elem);
+            } catch (URISyntaxException e) {
+                logger.warn(line + "URI could not be parsed: " + e.getMessage());
+            }
+        }
+
+        return name;
+    }
+
+    /**
+     * @param outputCollation
+     * @return
+     */
+    private String[] makeVolumeDetail(String outputCollation) {
+        if (outputCollation == null){
+            return new String[0];
+        }else{
+            String[] split = outputCollation.split(":");
+            return split;
+        }
+    }
+
+    /**
+     * @param state
+     * @param referencedName
+     */
+    private void addNomRefExtension(SimpleExcelTaxonImportState<CONFIG> state, BotanicalName name) {
+        String newExtensionStr = name.getFullTitleCache() + " - BORHIDI";
+        UUID uuidNomRefExtension = MexicoConabioTransformer.uuidNomRefExtension;
+        for (Extension extension : name.getExtensions()){
+            if (extension.getType().getUuid().equals(uuidNomRefExtension)){
+                extension.setValue(extension.getValue() + "\n" + newExtensionStr);
+                return;
+            }
+        }
+        String label = "Nomenclatural reference in Sources";
+        String abbrev = "Nom. ref. src.";
+        ExtensionType extensionType = getExtensionType(state, uuidNomRefExtension, label, label, abbrev);
+        Extension.NewInstance(name, newExtensionStr, extensionType);
+    }
+
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiImportConfigurator.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiImportConfigurator.java
new file mode 100644 (file)
index 0000000..4b99027
--- /dev/null
@@ -0,0 +1,60 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.net.URI;
+
+import eu.etaxonomy.cdm.database.ICdmDataSource;
+import eu.etaxonomy.cdm.io.common.ImportStateBase;
+import eu.etaxonomy.cdm.io.common.mapping.IInputTransformer;
+import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoBorhidiImportConfigurator extends ExcelImportConfiguratorBase{
+    private static final long serialVersionUID = -4793138681632122831L;
+
+    private static IInputTransformer defaultTransformer = new MexicoBorhidiTransformer();
+
+    /**
+     * @param source
+     * @param cdmDestination
+     * @return
+     */
+    public static MexicoBorhidiImportConfigurator NewInstance(URI source, ICdmDataSource destination) {
+        return new MexicoBorhidiImportConfigurator(source, destination);
+    }
+
+
+    private MexicoBorhidiImportConfigurator(URI source, ICdmDataSource destination) {
+        super(source, destination, defaultTransformer);
+        setNomenclaturalCode(NomenclaturalCode.ICNAFP);
+        setSource(source);
+        setDestination(destination);
+     }
+
+    @Override
+    public ImportStateBase getNewState() {
+        return new SimpleExcelTaxonImportState<>(this);
+    }
+
+    @Override
+    protected void makeIoClassList() {
+        ioClassList = new Class[]{
+                MexicoBorhidiExcelImport.class
+        };
+    }
+
+}
+
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiTransformer.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoBorhidiTransformer.java
new file mode 100644 (file)
index 0000000..2ca8724
--- /dev/null
@@ -0,0 +1,26 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.util.UUID;
+
+import eu.etaxonomy.cdm.io.common.mapping.InputTransformerBase;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoBorhidiTransformer extends InputTransformerBase{
+    private static final long serialVersionUID = 4308493883009041513L;
+
+    public static UUID uuidTropicosNameIdentifier = UUID.fromString("6205e531-75b0-4f2a-9a9c-b1247fb080ab");
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioCommonNamesImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioCommonNamesImport.java
new file mode 100644 (file)
index 0000000..258a8c9
--- /dev/null
@@ -0,0 +1,165 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import eu.etaxonomy.cdm.model.common.Language;
+import eu.etaxonomy.cdm.model.common.OriginalSourceType;
+import eu.etaxonomy.cdm.model.common.TermType;
+import eu.etaxonomy.cdm.model.common.TermVocabulary;
+import eu.etaxonomy.cdm.model.description.CommonTaxonName;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+@Component
+public class MexicoConabioCommonNamesImport<CONFIG extends MexicoConabioImportConfigurator>
+            extends SimpleExcelTaxonImport<CONFIG>{
+
+    private static final long serialVersionUID = 3579868489510261569L;
+
+    private static final Logger logger = Logger.getLogger(MexicoConabioCommonNamesImport.class);
+
+    private TermVocabulary<Language> languagesVoc;
+    private Map<String, Language> languagesMap = new HashMap<>();
+
+
+    @Override
+    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
+        initLanguageVocabulary(state);
+
+        String line = state.getCurrentLine() + ": ";
+        HashMap<String, String> record = state.getOriginalRecord();
+
+        String idCat = getValue(record, "IdCAT");
+        Taxon taxon = state.getHigherTaxon(idCat);
+        if (taxon == null){
+            logger.warn(line + "Taxon could not be found: " + idCat);
+        }else{
+            TaxonDescription desc = getTaxonDescription(taxon);
+            String nomComunStr = getValue(record, "NomComun");
+            String langStr = getValue(record, "Lengua");
+            Language language = languagesMap.get(langStr);
+            if (language == null){
+                logger.warn("Language not found: " + langStr);
+            }
+
+            String refStr = getValue(record, "ReferenciasNombreComun");
+            CommonTaxonName commonName = CommonTaxonName.NewInstance(nomComunStr,
+                    language, null);
+
+            Reference ref = getReference(state, refStr);
+            if (ref != null){
+                commonName.addSource(OriginalSourceType.PrimaryTaxonomicSource,
+                        null, null, ref, null);
+            }
+
+
+            getTaxonService().save(taxon);
+        }
+    }
+
+    /**
+     * @param state
+     */
+    @SuppressWarnings("unchecked")
+    private void initLanguageVocabulary(SimpleExcelTaxonImportState<CONFIG> state) {
+        if (languagesVoc == null){
+            languagesVoc = this.getVocabularyService().find(MexicoConabioTransformer.uuidMexicanLanguagesVoc);
+            if (languagesVoc == null){
+                createLanguagesVoc(state);
+            }
+        }
+    }
+
+    /**
+     * @param state
+     * @return
+     */
+    private void createLanguagesVoc(SimpleExcelTaxonImportState<CONFIG> state) {
+        URI termSourceUri = null;
+        String label = "Mexican States";
+        String description = "Mexican States as used by the CONABIO Rubiaceae database";
+        languagesVoc = TermVocabulary.NewInstance(TermType.Language,
+                description, label, null, termSourceUri);
+        languagesVoc.setUuid(MexicoConabioTransformer.uuidMexicanLanguagesVoc);
+
+        addLanguage(state, "Aguascalientes", MexicoConabioTransformer.uuidAguascalientes);
+
+        this.getVocabularyService().save(languagesVoc);
+
+        return;
+    }
+
+    /**
+     * @param state
+     * @param string
+     * @param uuidaguascalientes
+     */
+    private void addLanguage(SimpleExcelTaxonImportState<CONFIG> state, String label, UUID uuid) {
+        String abbrev = null;
+        Language language = Language.NewInstance(
+                label, label, abbrev);
+        language.setUuid(uuid);
+        languagesVoc.addTerm(language);
+        languagesMap.put(label, language);
+    }
+
+    /**
+     * @param state
+     * @param refStr
+     * @return
+     */
+    private Reference getReference(SimpleExcelTaxonImportState<CONFIG> state, String refStr) {
+        if (StringUtils.isNoneBlank(refStr)){
+            return null;
+        }
+        Reference ref = state.getReference(refStr);
+        if (ref == null){
+            ref = ReferenceFactory.newBook();
+            ref.setTitleCache(refStr, true);
+            state.putReference(refStr, ref);
+        }
+        return ref;
+    }
+
+    /**
+     * @param taxon
+     * @return
+     */
+    private TaxonDescription getTaxonDescription(Taxon taxon) {
+        if (!taxon.getDescriptions().isEmpty()){
+            return taxon.getDescriptions().iterator().next();
+        }else{
+            TaxonDescription desc = TaxonDescription.NewInstance(taxon);
+            return desc;
+        }
+    }
+
+    @Override
+    protected boolean isIgnore(SimpleExcelTaxonImportState<CONFIG> state) {
+        return ! state.getConfig().isDoCommonNames();
+    }
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioDistributionImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioDistributionImport.java
new file mode 100644 (file)
index 0000000..0fd26ba
--- /dev/null
@@ -0,0 +1,255 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
+import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
+import eu.etaxonomy.cdm.model.common.OriginalSourceType;
+import eu.etaxonomy.cdm.model.common.TermType;
+import eu.etaxonomy.cdm.model.description.Distribution;
+import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
+import eu.etaxonomy.cdm.model.location.NamedArea;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+@Component
+public class MexicoConabioDistributionImport<CONFIG extends MexicoConabioImportConfigurator>
+            extends SimpleExcelTaxonImport<CONFIG> {
+
+    private static final long serialVersionUID = -1733208053395372094L;
+
+    private static final Logger logger = Logger.getLogger(MexicoConabioDistributionImport.class);
+
+    private OrderedTermVocabulary<NamedArea> stateAreasVoc;
+    private NamedArea mexico;
+
+    @Override
+    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
+        initAreaVocabulary(state);
+
+        String line = state.getCurrentLine() + ": ";
+        HashMap<String, String> record = state.getOriginalRecord();
+
+        String idCat = getValue(record, "IdCAT");
+        Taxon taxon = state.getHigherTaxon(idCat);
+        if (taxon == null){
+            logger.warn(line + "Taxon could not be found: " + idCat);
+        }else{
+            TaxonDescription desc = getTaxonDescription(taxon);
+
+            String distrStatusStr = getValue(record, "TipoDistribucion");
+            try {
+                PresenceAbsenceTerm mexicanDistributionStatus = state.getTransformer().getPresenceTermByKey(distrStatusStr);
+                if (mexicanDistributionStatus != null){
+                    Distribution mexicanDistribution = Distribution.NewInstance(mexico, mexicanDistributionStatus);
+                    desc.addElement(mexicanDistribution);
+                    String refStr = getValue(record, "ReferenciaTipoDistribucion");
+                    Reference ref = getReference(state, refStr);
+                    if (ref != null){
+                        mexicanDistribution.addSource(OriginalSourceType.PrimaryTaxonomicSource,
+                                null, null, ref, null);
+                    }
+
+                }
+            } catch (UndefinedTransformerMethodException e) {}
+
+
+            handleDistribution(state, desc, "AGUASCALIENTES", MexicoConabioTransformer.uuidAguascalientes, line);
+            handleDistribution(state, desc, "BAJA CALIFORNIA", MexicoConabioTransformer.uuidBaja_california, line);
+            handleDistribution(state, desc, "BAJA CALIFORNIA SUR", MexicoConabioTransformer.uuidBaja_california_sur, line);
+            handleDistribution(state, desc, "CAMPECHE", MexicoConabioTransformer.uuidCampeche, line);
+            handleDistribution(state, desc, "COAHUILA DE ZARAGOZA", MexicoConabioTransformer.uuidCoahuila_de_zaragoza, line);
+            handleDistribution(state, desc, "COLIMA", MexicoConabioTransformer.uuidColima, line);
+            handleDistribution(state, desc, "CHIAPAS", MexicoConabioTransformer.uuidChiapas, line);
+            handleDistribution(state, desc, "CHIHUAHUA", MexicoConabioTransformer.uuidChihuahua, line);
+            handleDistribution(state, desc, "DISTRITO FEDERAL", MexicoConabioTransformer.uuidDistrito_federal, line);
+            handleDistribution(state, desc, "DURANGO", MexicoConabioTransformer.uuidDurango, line);
+            handleDistribution(state, desc, "GUANAJUATO", MexicoConabioTransformer.uuidGuanajuato, line);
+            handleDistribution(state, desc, "GUERRERO", MexicoConabioTransformer.uuidGuerrero, line);
+            handleDistribution(state, desc, "HIDALGO", MexicoConabioTransformer.uuidHidalgo, line);
+            handleDistribution(state, desc, "JALISCO", MexicoConabioTransformer.uuidJalisco, line);
+            handleDistribution(state, desc, "MEXICO", MexicoConabioTransformer.uuidMexico, line);
+            handleDistribution(state, desc, "MICHOACAN DE OCAMPO", MexicoConabioTransformer.uuidMichoacan_de_ocampo, line);
+            handleDistribution(state, desc, "MORELOS", MexicoConabioTransformer.uuidMorelos, line);
+            handleDistribution(state, desc, "NAYARIT", MexicoConabioTransformer.uuidNayarit, line);
+            handleDistribution(state, desc, "NUEVO LEON", MexicoConabioTransformer.uuidNuevo_leon, line);
+            handleDistribution(state, desc, "OAXACA", MexicoConabioTransformer.uuidOaxaca, line);
+            handleDistribution(state, desc, "PUEBLA", MexicoConabioTransformer.uuidPuebla, line);
+            handleDistribution(state, desc, "QUERETARO DE ARTEAGA", MexicoConabioTransformer.uuidQueretaro_de_arteaga, line);
+            handleDistribution(state, desc, "QUINTANA ROO", MexicoConabioTransformer.uuidQuintana_roo, line);
+            handleDistribution(state, desc, "SAN LUIS POTOSI", MexicoConabioTransformer.uuidSan_luis_potosi, line);
+            handleDistribution(state, desc, "SINALOA", MexicoConabioTransformer.uuidSinaloa, line);
+            handleDistribution(state, desc, "SONORA", MexicoConabioTransformer.uuidSonora, line);
+            handleDistribution(state, desc, "TABASCO", MexicoConabioTransformer.uuidTabasco, line);
+            handleDistribution(state, desc, "TAMAULIPAS", MexicoConabioTransformer.uuidTamaulipas, line);
+            handleDistribution(state, desc, "TLAXCALA", MexicoConabioTransformer.uuidTlaxcala, line);
+            handleDistribution(state, desc, "VERACRUZ DE IGNACIO DE LA LLAVE", MexicoConabioTransformer.uuidVeracruz_de_ignacio_de_la_llave, line);
+            handleDistribution(state, desc, "YUCATAN", MexicoConabioTransformer.uuidYucatan, line);
+            handleDistribution(state, desc, "ZACATECAS", MexicoConabioTransformer.uuidZacatecas, line);
+
+            getTaxonService().save(taxon);
+        }
+
+
+    }
+
+    /**
+     * @param state
+     * @param refStr
+     * @return
+     */
+    private Reference getReference(SimpleExcelTaxonImportState<CONFIG> state, String refStr) {
+        if (StringUtils.isNoneBlank(refStr)){
+            return null;
+        }
+        Reference ref = state.getReference(refStr);
+        if (ref == null){
+            ref = ReferenceFactory.newBook();
+            ref.setTitleCache(refStr, true);
+            state.putReference(refStr, ref);
+        }
+        return ref;
+    }
+
+    /**
+     * @param desc
+     * @param string
+     * @param uuidUserDefinedAnnotationTypeVocabulary
+     */
+    private void handleDistribution(SimpleExcelTaxonImportState<CONFIG> state, TaxonDescription desc, String key,
+            UUID uuid, String line) {
+        HashMap<String, String> record = state.getOriginalRecord();
+        String value = getValue(record, key);
+        if ("1".equals(value)){
+            NamedArea area = getNamedArea(state, uuid, null, null, null, null, null);
+            Distribution dist = Distribution.NewInstance(area, PresenceAbsenceTerm.PRESENT());
+            desc.addElement(dist);
+        }else if (value != null){
+            logger.warn(line + "Unrecognized distribution status '"+value+"' for " + key);
+        }
+    }
+
+    /**
+     * @param taxon
+     * @return
+     */
+    private TaxonDescription getTaxonDescription(Taxon taxon) {
+        if (!taxon.getDescriptions().isEmpty()){
+            return taxon.getDescriptions().iterator().next();
+        }else{
+            TaxonDescription desc = TaxonDescription.NewInstance(taxon);
+            return desc;
+        }
+    }
+
+    /**
+     * @param state
+     */
+    @SuppressWarnings("unchecked")
+    private void initAreaVocabulary(SimpleExcelTaxonImportState<CONFIG> state) {
+        if (stateAreasVoc == null){
+            stateAreasVoc = (OrderedTermVocabulary<NamedArea>)this.getVocabularyService().find(MexicoConabioTransformer.uuidMexicanStatesVoc);
+            if (stateAreasVoc == null){
+                createStateAreasVoc(state);
+            }
+        }
+    }
+
+    /**
+     * @param state
+     * @return
+     */
+    private void createStateAreasVoc(SimpleExcelTaxonImportState<CONFIG> state) {
+        URI termSourceUri = null;
+        String label = "Mexican States";
+        String description = "Mexican States as used by the CONABIO Rubiaceae database";
+        stateAreasVoc = OrderedTermVocabulary.NewInstance(TermType.NamedArea,
+                description, label, null, termSourceUri);
+        stateAreasVoc.setUuid(MexicoConabioTransformer.uuidMexicanStatesVoc);
+
+        String mexicoLabel = "Mexico (Country)";
+        NamedArea newArea = NamedArea.NewInstance(
+                mexicoLabel, mexicoLabel, null);
+        newArea.setUuid(MexicoConabioTransformer.uuidMexicoCountry);
+        stateAreasVoc.addTerm(newArea);
+
+        addArea(state, "Aguascalientes", MexicoConabioTransformer.uuidAguascalientes);
+        addArea(state, "Baja California", MexicoConabioTransformer.uuidBaja_california);
+        addArea(state, "Baja California Sur", MexicoConabioTransformer.uuidBaja_california_sur);
+        addArea(state, "Campeche", MexicoConabioTransformer.uuidCampeche);
+        addArea(state, "Coahuila de Zaragoza", MexicoConabioTransformer.uuidCoahuila_de_zaragoza);
+        addArea(state, "Colima", MexicoConabioTransformer.uuidColima);
+        addArea(state, "Chiapas", MexicoConabioTransformer.uuidChiapas);
+        addArea(state, "Chihuahua", MexicoConabioTransformer.uuidChihuahua);
+        addArea(state, "Distrito ederal", MexicoConabioTransformer.uuidDistrito_federal);
+        addArea(state, "Durango", MexicoConabioTransformer.uuidDurango);
+        addArea(state, "Guanajuato", MexicoConabioTransformer.uuidGuanajuato);
+        addArea(state, "Guerrero", MexicoConabioTransformer.uuidGuerrero);
+        addArea(state, "Hidalgo", MexicoConabioTransformer.uuidHidalgo);
+        addArea(state, "Jalisco", MexicoConabioTransformer.uuidJalisco);
+        addArea(state, "Mexico", MexicoConabioTransformer.uuidMexico);
+        addArea(state, "Michoacan de Ocampo", MexicoConabioTransformer.uuidMichoacan_de_ocampo);
+        addArea(state, "Morelos", MexicoConabioTransformer.uuidMorelos);
+        addArea(state, "Nayarit", MexicoConabioTransformer.uuidNayarit);
+        addArea(state, "Nuevo Leon", MexicoConabioTransformer.uuidNuevo_leon);
+        addArea(state, "Oaxaca", MexicoConabioTransformer.uuidOaxaca);
+        addArea(state, "Puebla", MexicoConabioTransformer.uuidPuebla);
+        addArea(state, "Queretaro de Arteaga", MexicoConabioTransformer.uuidQueretaro_de_arteaga);
+        addArea(state, "Quintana Roo", MexicoConabioTransformer.uuidQuintana_roo);
+        addArea(state, "San luis Potosi", MexicoConabioTransformer.uuidSan_luis_potosi);
+        addArea(state, "Sinaloa", MexicoConabioTransformer.uuidSinaloa);
+        addArea(state, "Sonora", MexicoConabioTransformer.uuidSonora);
+        addArea(state, "Tabasco", MexicoConabioTransformer.uuidTabasco);
+        addArea(state, "Tamaulipas", MexicoConabioTransformer.uuidTamaulipas);
+        addArea(state, "Tlaxcala", MexicoConabioTransformer.uuidTlaxcala);
+        addArea(state, "Veracruz de Ignacio de la Llave", MexicoConabioTransformer.uuidVeracruz_de_ignacio_de_la_llave);
+        addArea(state, "Yucatan", MexicoConabioTransformer.uuidYucatan);
+        addArea(state, "Zacatecas", MexicoConabioTransformer.uuidZacatecas);
+
+        this.getVocabularyService().save(stateAreasVoc);
+
+        return;
+    }
+
+    /**
+     * @param state
+     * @param string
+     * @param uuidaguascalientes
+     */
+    private void addArea(SimpleExcelTaxonImportState<CONFIG> state, String areaLabel, UUID uuid) {
+        String abbrev = null;
+        NamedArea newArea = NamedArea.NewInstance(
+                areaLabel, areaLabel, abbrev);
+        newArea.setUuid(uuid);
+        newArea.setPartOf(mexico);
+        stateAreasVoc.addTerm(newArea);
+    }
+
+    @Override
+    protected boolean isIgnore(SimpleExcelTaxonImportState<CONFIG> state) {
+        return ! state.getConfig().isDoDistributions();
+    }
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioImportConfigurator.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioImportConfigurator.java
new file mode 100644 (file)
index 0000000..fb87f7f
--- /dev/null
@@ -0,0 +1,101 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.net.URI;
+
+import eu.etaxonomy.cdm.database.ICdmDataSource;
+import eu.etaxonomy.cdm.io.common.ImportStateBase;
+import eu.etaxonomy.cdm.io.common.mapping.IInputTransformer;
+import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoConabioImportConfigurator extends ExcelImportConfiguratorBase{
+    private static final long serialVersionUID = -2795059530001736347L;
+
+    private boolean doTaxa = true;
+    private boolean doDistributions = true;
+    private boolean doCommonNames = true;
+
+    private static IInputTransformer defaultTransformer = new MexicoConabioTransformer();
+
+    public static MexicoConabioImportConfigurator NewInstance(URI source, ICdmDataSource destination) {
+        return new MexicoConabioImportConfigurator(source, destination);
+    }
+
+    private MexicoConabioImportConfigurator(URI source, ICdmDataSource destination) {
+        super(source, destination, defaultTransformer);
+        setNomenclaturalCode(NomenclaturalCode.ICNAFP);
+        setSource(source);
+        setDestination(destination);
+     }
+
+    @SuppressWarnings({ "unchecked", "rawtypes" })
+    @Override
+    public ImportStateBase getNewState() {
+        return new SimpleExcelTaxonImportState<>(this);
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    protected void makeIoClassList() {
+        ioClassList = new Class[]{
+                MexicoConabioTaxonImport.class
+        };
+    }
+
+    /**
+     * @return the doTaxa
+     */
+    public boolean isDoTaxa() {
+        return doTaxa;
+    }
+
+    /**
+     * @param doTaxa the doTaxa to set
+     */
+    public void setDoTaxa(boolean doTaxa) {
+        this.doTaxa = doTaxa;
+    }
+
+    /**
+     * @return the doDistributions
+     */
+    public boolean isDoDistributions() {
+        return doDistributions;
+    }
+
+    /**
+     * @param doDistributions the doDistributions to set
+     */
+    public void setDoDistributions(boolean doDistributions) {
+        this.doDistributions = doDistributions;
+    }
+
+    /**
+     * @return the doCommonNames
+     */
+    public boolean isDoCommonNames() {
+        return doCommonNames;
+    }
+
+    /**
+     * @param doCommonNames the doCommonNames to set
+     */
+    public void setDoCommonNames(boolean doCommonNames) {
+        this.doCommonNames = doCommonNames;
+    }
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioImportState.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioImportState.java
new file mode 100644 (file)
index 0000000..8f19321
--- /dev/null
@@ -0,0 +1,34 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.io.excel.common.ExcelImportState;
+import eu.etaxonomy.cdm.io.excel.common.ExcelRowBase;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoConabioImportState extends ExcelImportState<MexicoConabioImportConfigurator, ExcelRowBase>{
+
+    @SuppressWarnings("unused")
+    private static final Logger logger = Logger.getLogger(MexicoConabioImportState.class);
+
+    /**
+     * @param config
+     */
+    public MexicoConabioImportState(MexicoConabioImportConfigurator config) {
+        super(config);
+    }
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioTaxonImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioTaxonImport.java
new file mode 100644 (file)
index 0000000..0e20214
--- /dev/null
@@ -0,0 +1,354 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+
+import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
+import eu.etaxonomy.cdm.model.agent.Person;
+import eu.etaxonomy.cdm.model.agent.Team;
+import eu.etaxonomy.cdm.model.common.Annotation;
+import eu.etaxonomy.cdm.model.common.AnnotationType;
+import eu.etaxonomy.cdm.model.common.Extension;
+import eu.etaxonomy.cdm.model.common.ExtensionType;
+import eu.etaxonomy.cdm.model.common.Language;
+import eu.etaxonomy.cdm.model.common.TimePeriod;
+import eu.etaxonomy.cdm.model.name.BotanicalName;
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+import eu.etaxonomy.cdm.model.name.NomenclaturalStatus;
+import eu.etaxonomy.cdm.model.name.NomenclaturalStatusType;
+import eu.etaxonomy.cdm.model.name.NonViralName;
+import eu.etaxonomy.cdm.model.name.Rank;
+import eu.etaxonomy.cdm.model.name.TaxonNameBase;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.model.taxon.Classification;
+import eu.etaxonomy.cdm.model.taxon.Synonym;
+import eu.etaxonomy.cdm.model.taxon.SynonymRelationshipType;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
+import eu.etaxonomy.cdm.strategy.parser.TimePeriodParser;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+@Component
+public class MexicoConabioTaxonImport<CONFIG extends MexicoConabioImportConfigurator>
+        extends SimpleExcelTaxonImport<CONFIG>{
+
+    private static final long serialVersionUID = 3691221053127007258L;
+
+    private static final Logger logger = Logger.getLogger(MexicoConabioTaxonImport.class);
+
+    private final Map<String, TaxonBase<?>> taxonIdMap = new HashMap<>();
+
+    private Classification classification;
+
+
+    private  static List<String> expectedKeys= Arrays.asList(new String[]{
+            "IdCAT","IdCATRel","IdCAT_AscendenteInmediato"
+            ,"IdCAT_AscendenteObligatorio","CategoriaTaxonomica","Nombre",
+            "EstatusNombre","AutorNombre","AutorSinAnio","Anio",
+            "ReferenciaNombre",
+            "Division","AutorDivision","ReferenciaClasificacionDivision",
+            "Clase","AutorClase","ReferenciaClasificacionClase",
+            "Subclase","AutorSubclase","ReferenciaClasificacionSubclase",
+            "Superorden","AutorSuperorden","ReferenciaClasificacionSuperorden",
+            "Orden","AutorOrden","ReferenciaClasificacionOrden",
+            "Familia",     "EstatusFamilia","AutorFamilia","ReferenciaClasificacionFamilia",
+            "Tribu",  "EstatusTribu","AutorTribu","ReferenciaNombreTribu",
+            "Genero","EstatusGenero","AutorGenero","","ReferenciaNombreGenero",
+            "Epiteto_especifico","EstatusEspecie","AutorEpiteto_especifico","ReferenciaNombreEspecie",
+            "CategoriaInfraespecifica","NombreInfraespecifico","EstatusInfraespecie","AutorInfraespecie","ReferenciaNombreInfraespecifico",
+            "CitaNomenclatural","Anotacion al Taxon","Fuente_BDs",
+            "FamAceptada","GenAceptado","CategoriaTaxAceptada","NombreAceptado","AutorNombreAceptado","AutorSinAnioAceptado","AnioAceptado",
+            "TipoRelacion","ReferenciaSinonimia","ComentariosRevisor",
+            "CompareID","IdCAT_OLD","Nombre_OLD","AutorSinAnio_OLD",
+            "CitaNomenclatural_OLD","ReferenceType","IsUpdated"
+        });
+
+
+    @Override
+    protected void firstPass(SimpleExcelTaxonImportState<CONFIG> state) {
+        String line = state.getCurrentLine() + ": ";
+        HashMap<String, String> record = state.getOriginalRecord();
+
+        Set<String> keys = record.keySet();
+
+        checkAllKeysExist(line, keys, expectedKeys);
+
+        if (getValue(record, "Nombre") == null ){
+            logger.warn("No FullnameNoAuthors given: " + line);
+            return;
+        }
+
+        //Name
+        BotanicalName speciesName = makeName(line, record, state);
+        String statusStr = getValue(record, "EstatusNombre");
+
+        String secRefStr = getValueNd(record, "ReferenciaNombre");
+        Reference sec = getSecRef(state, secRefStr, line);
+
+        TaxonBase<?> taxonBase;
+        if ("aceptado".equals(statusStr)){
+            taxonBase = Taxon.NewInstance(speciesName, sec);
+        }else if (statusStr.startsWith("sin")){
+            taxonBase = Synonym.NewInstance(speciesName, sec);
+        }else{
+            throw new RuntimeException(line + " Status not recognized: " + statusStr);
+        }
+
+        String annotation = getValue(record, "Anotacion al Taxon");
+        if (annotation != null && (!annotation.equals("nom. illeg.") || !annotation.equals("nom. cons."))){
+            taxonBase.addAnnotation(Annotation.NewInstance(annotation, AnnotationType.EDITORIAL(), Language.SPANISH_CASTILIAN()));
+        }
+
+        String idCat = getValue(record, "IdCAT");
+        this.addOriginalSource(taxonBase, idCat, "IdCAT", state.getConfig().getSourceReference());
+
+        getTaxonService().save(taxonBase);
+        taxonIdMap.put(idCat, taxonBase);
+        if (taxonBase instanceof Taxon){
+            state.putHigherTaxon(idCat, (Taxon)taxonBase);
+        }
+
+    }
+
+
+
+    /**
+     * @param state
+     * @param secRefStr
+     * @return
+     */
+    private Reference getSecRef(SimpleExcelTaxonImportState<CONFIG> state, String secRefStr, String line) {
+        Reference result = state.getReference(secRefStr);
+        if (result == null && secRefStr != null){
+            result = ReferenceFactory.newBook();
+            TimePeriod tp = TimePeriodParser.parseString(secRefStr.substring(secRefStr.length()-4));
+            String authorStr = secRefStr.substring(0, secRefStr.length()-6);
+            if (! (authorStr + ", " + tp.getYear()).equals(secRefStr)){
+                logger.warn(line + "Sec ref could not be parsed: " + secRefStr);
+            }else{
+                result.setDatePublished(tp);
+            }
+
+            if (authorStr.contains(",") || authorStr.contains("&")){
+                //TODO split
+                Team team = Team.NewTitledInstance(authorStr, null);
+                result.setAuthorship(team);
+            }else if (authorStr.equals("Tropicos") || authorStr.equals("The plant list")
+                    || authorStr.equals("APG IV")){
+                result.setTitle(authorStr);
+
+            }else{
+                Person person = Person.NewTitledInstance(authorStr);
+                result.setAuthorship(person);
+            }
+
+        }else if(secRefStr == null){
+            logger.warn(line + "Empty secRefStr not yet implemented");
+        }
+
+        return result;
+    }
+
+
+
+    /**
+     * @param record
+     * @param state
+     * @return
+     */
+    private BotanicalName makeName(String line, HashMap<String, String> record, SimpleExcelTaxonImportState<CONFIG> state) {
+
+        String authorStr = getValueNd(record, "AutorSinAnio");
+        String nameStr = getValue(record, "Nombre");
+        String fullNameStr = nameStr + (authorStr != null ? " " + authorStr : "");
+        String nomRefStr = getValue(record, "CitaNomenclatural");
+        String refType = getValue(record, "ReferenceType");
+        String idCat = getValue(record, "IdCAT");
+        String rankStr = getValue(record, "CategoriaTaxonomica");
+        String annotation = getValue(record, "Anotacion al Taxon");
+        Rank rank = null;
+        try {
+            rank = state.getTransformer().getRankByKey(rankStr);
+        } catch (UndefinedTransformerMethodException e) {
+            logger.warn(line + "Rank not recognized: " + rankStr);
+        }
+
+        BotanicalName fullName = (BotanicalName)nameParser.parseFullName(fullNameStr, NomenclaturalCode.ICNAFP, rank);
+        if (fullName.isProtectedTitleCache()){
+            logger.warn(line + "Name could not be parsed: " + fullNameStr );
+        }else{
+            replaceAuthorNames(state, fullName);
+        }
+        BotanicalName existingName = getExistingName(state, fullName);
+
+        String refNameStr = fullNameStr;
+        if ("A".equals(refType)){  //Article
+            refNameStr = fullNameStr + " in " + nomRefStr;
+        }else if ("B".equals(refType)){   //Book
+            refNameStr = fullNameStr + ", " + nomRefStr;
+        }
+
+        BotanicalName referencedName = (BotanicalName)nameParser.parseFullName(refNameStr, NomenclaturalCode.ICNAFP, rank);
+        if (referencedName.isProtectedFullTitleCache() || referencedName.isProtectedTitleCache()){
+            logger.warn(line + "Referenced name could not be parsed: " + refNameStr );
+            BotanicalName tmp = (BotanicalName)nameParser.parseFullName(refNameStr, NomenclaturalCode.ICNAFP, rank);
+
+        }else{
+            replaceAuthorNames(state, referencedName);
+        }
+
+        BotanicalName result= referencedName;
+        if (existingName != null){
+            String existingRefTitle = existingName.getFullTitleCache();
+            String conabioRefTitle = referencedName.getFullTitleCache();
+            addNomRefExtension(state, referencedName);
+            if (!existingRefTitle.equals(conabioRefTitle)){
+                existingName.setNomenclaturalMicroReference(referencedName.getNomenclaturalMicroReference());
+                existingName.setNomenclaturalReference(referencedName.getNomenclaturalReference());
+                result = existingName;
+            }
+        }
+
+        if (annotation != null && (annotation.equals("nom. illeg.") || annotation.equals("nom. cons."))){
+            try {
+                NomenclaturalStatusType nomStatusType = NomenclaturalStatusType.getNomenclaturalStatusTypeByAbbreviation(annotation, result);
+                result.addStatus(NomenclaturalStatus.NewInstance(nomStatusType));
+            } catch (UnknownCdmTypeException e) {
+                logger.warn(line + "nomStatusType not recognized: " + annotation);
+            }
+        }
+
+        this.addOriginalSource(result, idCat, "IdCAT", state.getConfig().getSourceReference());
+
+        return result;
+    }
+
+    /**
+     * @param state
+     * @param referencedName
+     */
+    private void addNomRefExtension(SimpleExcelTaxonImportState<CONFIG> state, BotanicalName name) {
+        String newExtensionStr = name.getFullTitleCache() + " - CONABIO";
+        UUID uuidNomRefExtension = MexicoConabioTransformer.uuidNomRefExtension;
+        for (Extension extension : name.getExtensions()){
+            if (extension.getType().getUuid().equals(uuidNomRefExtension)){
+                extension.setValue(extension.getValue() + "\n" + newExtensionStr);
+                return;
+            }
+        }
+        String label = "Nomenclatural reference in Sources";
+        String abbrev = "Nom. ref. src.";
+        ExtensionType extensionType = getExtensionType(state, uuidNomRefExtension, label, label, abbrev);
+        Extension.NewInstance(name, newExtensionStr, extensionType);
+    }
+
+    boolean nameMapIsInitialized = false;
+    /**
+     * @param state
+     * @param fullName
+     * @return
+     */
+    @SuppressWarnings("rawtypes")
+    private BotanicalName getExistingName(SimpleExcelTaxonImportState<CONFIG> state, BotanicalName fullName) {
+        if (!nameMapIsInitialized){
+            List<String> propertyPaths = Arrays.asList("");
+            List<TaxonNameBase> existingNames = this.getNameService().list(null, null, null, null, propertyPaths);
+            for (TaxonNameBase tnb : existingNames){
+                state.putName(tnb.getTitleCache(), (NonViralName<?>)tnb);
+            }
+            nameMapIsInitialized = true;
+        }
+        return (BotanicalName)state.getName(fullName.getTitleCache());
+    }
+
+    /**
+     * @param record
+     * @param string
+     * @return
+     */
+    private String getValueNd(HashMap<String, String> record, String string) {
+        String value = getValue(record, string);
+        if ("ND".equals(value)){
+            return null;
+        }else{
+            return value;
+        }
+    }
+
+
+    @Override
+    protected void secondPass(SimpleExcelTaxonImportState<CONFIG> state) {
+//        IdCAT_AscendenteInmediato, IdCATRel, TipoRelacion
+        HashMap<String, String> record = state.getOriginalRecord();
+        String line = state.getCurrentLine() + ": ";
+
+        String parentStr = getValue(record, "IdCAT_AscendenteInmediato");
+        String relStr = getValue(record, "IdCATRel");
+
+        String statusStr = getValue(record, "EstatusNombre");
+
+        Classification classification = getClassification(state);
+        String idCat = getValue(record, "IdCAT");
+        TaxonBase<?> taxonBase = taxonIdMap.get(idCat);
+        Taxon parent;
+        if ("aceptado".equals(statusStr)){
+            parent = (Taxon)taxonIdMap.get(parentStr);
+            if (parent == null){
+                logger.warn(line + "Parent is missing: "+ parentStr);
+            }else{
+                Reference relRef = null;  //TODO
+                classification.addParentChild(parent, (Taxon)taxonBase, relRef, null);
+            }
+        }else if (statusStr.startsWith("sin")){
+            parent = (Taxon)taxonIdMap.get(relStr);
+            if (parent == null){
+                logger.warn(line + "Parent is missing: "+ relStr);
+            }else{
+                Reference synRef = null; //null
+                parent.addSynonym((Synonym)taxonBase, SynonymRelationshipType.SYNONYM_OF(), synRef, null);
+            }
+        }
+    }
+
+     /**
+     * @return
+     */
+    private Classification getClassification(SimpleExcelTaxonImportState<CONFIG> state) {
+        if (classification == null){
+            MexicoConabioImportConfigurator config = state.getConfig();
+            classification = Classification.NewInstance(config.getClassificationName());
+            classification.setUuid(config.getClassificationUuid());
+            classification.setReference(config.getSourceReference());
+            getClassificationService().save(classification);
+        }
+        return classification;
+    }
+
+
+    @Override
+    protected boolean isIgnore(SimpleExcelTaxonImportState<CONFIG> state) {
+        return ! state.getConfig().isDoTaxa();
+    }
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioTransformer.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/MexicoConabioTransformer.java
new file mode 100644 (file)
index 0000000..4560e26
--- /dev/null
@@ -0,0 +1,140 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.io.common.mapping.InputTransformerBase;
+import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
+import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
+import eu.etaxonomy.cdm.model.name.Rank;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class MexicoConabioTransformer extends InputTransformerBase{
+
+    private static final long serialVersionUID = -5618949703252325141L;
+
+    private static final Logger logger = Logger.getLogger(MexicoConabioTransformer.class);
+
+    public static final UUID uuidNomRefExtension = UUID.fromString("0a7e2f5f-c62d-43e1-874a-07cb1dbb9fa0");
+
+    public static final UUID uuidMexicanStatesVoc = UUID.fromString("88556d4c-a171-4e14-ac56-3154d88f429b");
+
+    public static final UUID uuidMexicoCountry = UUID.fromString("b451ccd8-dd40-4804-b507-1ba46fad151a");
+    public static final UUID uuidAguascalientes = UUID.fromString("fff6867a-bfa4-479b-8f35-bf273a790c8f");
+    public static final UUID uuidBaja_california = UUID.fromString("a76e3818-37b6-4854-aaf7-fa02d0a99d02");
+    public static final UUID uuidBaja_california_sur = UUID.fromString("f298f095-5d55-49bd-9e1c-6aedee9e53ae");
+    public static final UUID uuidCampeche = UUID.fromString("1f955f0f-1a63-406b-951f-426f55f32f54");
+    public static final UUID uuidCoahuila_de_zaragoza = UUID.fromString("eb9ff874-d598-4b1c-b1b8-97c33c69155f");
+    public static final UUID uuidColima = UUID.fromString("f3da7526-21a9-4ac0-bf3f-56bc9ea699d5");
+    public static final UUID uuidChiapas = UUID.fromString("413e70cc-a39c-4b00-af60-82a3650aba0f");
+    public static final UUID uuidChihuahua = UUID.fromString("8a94f64d-822b-4dea-9161-9f130ca22850");
+    public static final UUID uuidDistrito_federal = UUID.fromString("5686a49e-e40d-4bc5-b0c7-d2bcb489baed");
+    public static final UUID uuidDurango = UUID.fromString("a0b4c414-95c1-4d1f-b6de-589baec83890");
+    public static final UUID uuidGuanajuato = UUID.fromString("641de041-f468-4c46-84f8-bbc9e6eb2db0");
+    public static final UUID uuidGuerrero = UUID.fromString("2c4a7e98-154c-480c-804d-0acf285087b4");
+    public static final UUID uuidHidalgo = UUID.fromString("40c40034-c712-4793-87ba-1523d0a17411");
+    public static final UUID uuidJalisco = UUID.fromString("315c8fb8-08d6-4acc-acad-d7c3ab02a6b7");
+    public static final UUID uuidMexico = UUID.fromString("0730370d-66c8-4e1f-a40b-c8941edc12d3");
+    public static final UUID uuidMichoacan_de_ocampo = UUID.fromString("aaf89369-139b-4524-8f2d-5010aab755c7");
+    public static final UUID uuidMorelos = UUID.fromString("c9a5cd7e-6828-4505-8e74-b2e0e56d0f0a");
+    public static final UUID uuidNayarit = UUID.fromString("6f3cf768-7b22-4351-98db-e47f88501d8c");
+    public static final UUID uuidNuevo_leon = UUID.fromString("5ce156f4-db40-4404-8610-b46727e93252");
+    public static final UUID uuidOaxaca = UUID.fromString("47a15fd7-4d5f-4d03-949b-0ffc873f112e");
+    public static final UUID uuidPuebla = UUID.fromString("e1c52112-cb27-4bdf-a891-9da8eed591e8");
+    public static final UUID uuidQueretaro_de_arteaga = UUID.fromString("d09512dc-d3c8-4454-a595-cd610790e9b9");
+    public static final UUID uuidQuintana_roo = UUID.fromString("bf2ade90-12fd-48eb-9425-9932a0333d90");
+    public static final UUID uuidSan_luis_potosi = UUID.fromString("cd54fd65-b5f2-4109-bd5e-6cb935eace1f");
+    public static final UUID uuidSinaloa = UUID.fromString("924dc40f-63f3-4a25-9b64-8700710409de");
+    public static final UUID uuidSonora = UUID.fromString("2b8dc6bb-5ccc-44bc-b34b-17b9faa620cb");
+    public static final UUID uuidTabasco = UUID.fromString("430f94ee-6e12-40c4-be39-7563017c359a");
+    public static final UUID uuidTamaulipas = UUID.fromString("99caa082-d67e-4025-9d73-110f0edf862d");
+    public static final UUID uuidTlaxcala = UUID.fromString("a06acf81-8d76-40ec-83fa-15a0fa0e8b95");
+    public static final UUID uuidVeracruz_de_ignacio_de_la_llave = UUID.fromString("0f98fcb1-7345-49f5-af6f-5f781a525a3a");
+    public static final UUID uuidYucatan = UUID.fromString("5dd5d5fa-77f0-42f6-a45c-384130e5f16d");
+    public static final UUID uuidZacatecas = UUID.fromString("0e9bc1f2-0154-4424-85c7-1bfc8cf3696c");
+
+
+    public static final UUID uuidMexicanLanguagesVoc = UUID.fromString("d37d043e-94af-4cb0-b702-e6f45318b039");
+
+    public static final UUID uuidChontal = UUID.fromString("e2ea70d0-605b-4e21-9848-aefe38ea6abb");
+    public static final UUID uuidChinanteco = UUID.fromString("18394cf7-9027-4253-be77-a136f8293d37");
+    public static final UUID uuidChiapaneca = UUID.fromString("bd98cda2-3fc3-432a-b283-06acbeba054c");
+    public static final UUID uuidHuasteco = UUID.fromString("dff1a7d4-7520-4ad3-9cdb-7fa9d8ee4989");
+    public static final UUID uuidEspanol_Maya = UUID.fromString("ebd5fb21-628c-424e-9add-bf29a1e51b28");
+    public static final UUID uuidGuarijio = UUID.fromString("f7064648-a033-40f5-b271-9c577c123a30");
+    public static final UUID uuidHuave = UUID.fromString("494abcf2-d027-4cc4-a48e-4c5a55e205a9");
+    public static final UUID uuidEspanol = UUID.fromString("fffdc8a6-a8c3-4914-b108-d3397140a692");
+    public static final UUID uuidMaya = UUID.fromString("3c1a6981-13c1-410f-8b8d-b99612db7aba");
+    public static final UUID uuidLacandon = UUID.fromString("6ca007a9-6c7b-4381-a5ae-c29177b6ee6c");
+    public static final UUID uuidIngles = UUID.fromString("90affeb7-cb08-4095-98de-74923c02e98f");
+    public static final UUID uuidItzmal = UUID.fromString("68c0c780-c724-419f-9797-2311d091d817");
+    public static final UUID uuidNahuatl = UUID.fromString("4c487f72-2e57-4a8c-96c2-52047c812cda");
+    public static final UUID uuidTarahumara = UUID.fromString("98e67390-b41f-4763-ac27-eddf978f4e5d");
+    public static final UUID uuidOtomi = UUID.fromString("0b7a6fdb-a797-4551-81b8-d2ad51048d4a");
+    public static final UUID uuidMixe = UUID.fromString("9c9a9752-a3b4-46b6-bb9a-481e22027d4d");
+    public static final UUID uuidTseltal = UUID.fromString("7cc0b188-cfa6-42e0-9641-38aeb6a6ec3b");
+    public static final UUID uuidZapoteco = UUID.fromString("9ad65652-5b14-4580-9b4e-28e0a28753b4");
+    public static final UUID uuidTotonaco = UUID.fromString("2eae8d72-a45c-48be-b9a4-aaf96d21df0a");
+    public static final UUID uuidTarasco = UUID.fromString("cf597916-0422-495f-bf0b-ea0841e32a52");
+
+
+    @Override
+    public Rank getRankByKey(String key) throws UndefinedTransformerMethodException {
+        if (StringUtils.isBlank(key)){
+            return null;
+        }else if (key.equals("orden")) {return Rank.ORDER();
+        }else if (key.equals("subclase")){return Rank.SUBCLASS();
+        }else if (key.equals("clase")){return Rank.CLASS();
+        }else if (key.equals("familia")){return Rank.FAMILY();
+        }else if (key.equals("tribu")){return Rank.TRIBE();
+        }else if (key.equals("superorden")){return Rank.SUPERORDER();
+        }else if (key.equals("división")){return Rank.DIVISION();
+
+        }else if (key.equals("género")){return Rank.GENUS();
+        }else if (key.equals("especie")){return Rank.SPECIES();
+        }else if (key.equals("subespecie")){return Rank.SUBSPECIES();
+        }else if (key.equals("variedad")){return Rank.VARIETY();
+        }else{
+            logger.warn("Rank not defined: " + key);
+            return null;
+        }
+    }
+
+
+    @Override
+    public PresenceAbsenceTerm getPresenceTermByKey(String key) throws UndefinedTransformerMethodException {
+        if (StringUtils.isBlank(key)){
+            return null;
+        }else if (key.equals("Endémica")){
+            return PresenceAbsenceTerm.ENDEMIC_FOR_THE_RELEVANT_AREA();
+        }else{
+            logger.warn("PresenceTerm not yet implemented: " + key);
+            return null;
+        }
+    }
+
+
+    @Override
+    public UUID getPresenceTermUuid(String key) throws UndefinedTransformerMethodException {
+        // TODO Auto-generated method stub
+        return super.getPresenceTermUuid(key);
+    }
+
+
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/SimpleExcelTaxonImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/SimpleExcelTaxonImport.java
new file mode 100644 (file)
index 0000000..97ec822
--- /dev/null
@@ -0,0 +1,209 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
+import eu.etaxonomy.cdm.io.excel.common.ExcelImporterBase;
+import eu.etaxonomy.cdm.model.agent.Person;
+import eu.etaxonomy.cdm.model.agent.Team;
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;
+import eu.etaxonomy.cdm.model.name.BotanicalName;
+import eu.etaxonomy.cdm.model.name.Rank;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonNode;
+import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
+import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
+
+/**
+ * Simple Excel import class that works without default state class
+ * {@link SimpleExcelTaxonImportState}
+ * @author a.mueller
+ * @date 16.06.2016
+ */
+public abstract class SimpleExcelTaxonImport<CONFIG extends ExcelImportConfiguratorBase>
+        extends ExcelImporterBase<SimpleExcelTaxonImportState<CONFIG>>{
+
+    private static final long serialVersionUID = -4345647703312616421L;
+
+    private static final Logger logger = Logger.getLogger(SimpleExcelTaxonImport.class);
+
+    protected static INonViralNameParser<?> nameParser = NonViralNameParserImpl.NewInstance();
+
+
+    @Override
+    protected void analyzeRecord(HashMap<String, String> record, SimpleExcelTaxonImportState<CONFIG> state) {
+        //override only if needed
+    }
+
+//    @Override
+//    protected void firstPass(SimpelExcelTaxonImportState<CONFIG> state) {
+//        // TODO Auto-generated method stub
+//    }
+
+    @Override
+    protected void secondPass(SimpleExcelTaxonImportState<CONFIG> state) {
+        //override only if needed
+    }
+
+    @Override
+    protected boolean isIgnore(SimpleExcelTaxonImportState<CONFIG> state) {
+        return false;
+    }
+
+//***************************** METHODS *********************************/
+    /**
+     * Returns the value of the record map for the given key.
+     * The value is trimmed and empty values are set to <code>null</code>.
+     * @param record
+     * @param originalKey
+     * @return
+     */
+    protected String getValue(Map<String, String> record, String originalKey) {
+        String value = record.get(originalKey);
+        if (! StringUtils.isBlank(value)) {
+            if (logger.isDebugEnabled()) { logger.debug(originalKey + ": " + value); }
+            value = CdmUtils.removeDuplicateWhitespace(value.trim()).toString();
+            return value;
+        }else{
+            return null;
+        }
+    }
+
+    /**
+     * @param state
+     * @return
+     */
+    protected IdentifiableSource makeOriginalSource(SimpleExcelTaxonImportState<CONFIG> state) {
+        return IdentifiableSource.NewDataImportInstance("line: " + state.getCurrentLine(), null, state.getConfig().getSourceReference());
+    }
+
+    /**
+     * @param state
+     * @param speciesName
+     * @param sec
+     * @param taxon
+     * @param familyNode
+     */
+    protected void makeGenus(SimpleExcelTaxonImportState<CONFIG> state,
+            BotanicalName speciesName,
+            Reference sec,
+            Taxon taxon,
+            TaxonNode familyNode) {
+
+        TaxonNode higherNode;
+        if (speciesName.isProtectedTitleCache()){
+            higherNode = familyNode;
+        }else{
+            String genusStr = speciesName.getGenusOrUninomial();
+            Taxon genus = state.getHigherTaxon(genusStr);
+            if (genus != null){
+                higherNode = genus.getTaxonNodes().iterator().next();
+            }else{
+                BotanicalName genusName = BotanicalName.NewInstance(Rank.GENUS());
+                genusName.addSource(makeOriginalSource(state));
+                genusName.setGenusOrUninomial(genusStr);
+                genus = Taxon.NewInstance(genusName, sec);
+                genus.addSource(makeOriginalSource(state));
+                higherNode = familyNode.addChildTaxon(genus, null, null);
+                state.putHigherTaxon(genusStr, genus);
+            }
+        }
+
+        higherNode.addChildTaxon(taxon, null, null);
+        taxon.addSource(makeOriginalSource(state));
+    }
+
+    /**
+     * @param line
+     * @param keys
+     * @param expectedKeys
+     */
+    protected void checkAllKeysExist(String line, Set<String> keys, List<String> expectedKeys) {
+        for (String key: keys) {
+            if (! expectedKeys.contains(key)){
+                logger.warn(line + "Unexpected Key: " + key);
+            }
+        }
+    }
+
+
+    /**
+     * @param state
+     * @param name
+     */
+    protected void replaceAuthorNames(SimpleExcelTaxonImportState<CONFIG> state, BotanicalName name) {
+        TeamOrPersonBase<?> combAuthor = name.getCombinationAuthorship();
+        name.setCombinationAuthorship(getExistingAuthor(state, combAuthor));
+
+        TeamOrPersonBase<?> exAuthor = name.getExCombinationAuthorship();
+        name.setExCombinationAuthorship(getExistingAuthor(state, exAuthor));
+
+        TeamOrPersonBase<?> basioAuthor = name.getBasionymAuthorship();
+        name.setBasionymAuthorship(getExistingAuthor(state, basioAuthor));
+
+        TeamOrPersonBase<?> exBasioAuthor = name.getExBasionymAuthorship();
+        name.setExBasionymAuthorship(getExistingAuthor(state, exBasioAuthor));
+
+    }
+
+    /**
+     * @param state
+     * @param combAuthor
+     * @return
+     */
+    protected TeamOrPersonBase<?> getExistingAuthor(SimpleExcelTaxonImportState<CONFIG> state,
+            TeamOrPersonBase<?> author) {
+        if (author == null){
+            return null;
+        }else{
+            TeamOrPersonBase<?> result = state.getAgentBase(author.getTitleCache());
+            if (result == null){
+                state.putAgentBase(author.getTitleCache(), author);
+                if (author instanceof Team){
+                    handleTeam(state, (Team)author);
+                }
+                result = author;
+            }
+            return result;
+        }
+    }
+
+    /**
+     * @param state
+     * @param author
+     */
+    private void handleTeam(SimpleExcelTaxonImportState<CONFIG> state, Team team) {
+        List<Person> members = team.getTeamMembers();
+        for (int i =0; i< members.size(); i++){
+            Person person = members.get(i);
+            //FIXME cast find a better way to guarantee that only persons are returned
+            Person existingPerson = (Person)state.getAgentBase(person.getTitleCache());
+            if (existingPerson != null){
+                members.set(i, existingPerson);
+            }else{
+                state.putAgentBase(person.getTitleCache(), person);
+            }
+        }
+
+    }
+
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/SimpleExcelTaxonImportState.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/mexico/SimpleExcelTaxonImportState.java
new file mode 100644 (file)
index 0000000..4abf52e
--- /dev/null
@@ -0,0 +1,91 @@
+// $Id$
+/**
+* Copyright (C) 2016 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+package eu.etaxonomy.cdm.io.mexico;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.io.excel.common.ExcelImportConfiguratorBase;
+import eu.etaxonomy.cdm.io.excel.common.ExcelImportState;
+import eu.etaxonomy.cdm.io.excel.common.ExcelRowBase;
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.name.NonViralName;
+import eu.etaxonomy.cdm.model.reference.Reference;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+
+/**
+ * @author a.mueller
+ * @date 16.06.2016
+ *
+ */
+public class SimpleExcelTaxonImportState<CONFIG extends ExcelImportConfiguratorBase>
+        extends ExcelImportState<CONFIG, ExcelRowBase>{
+
+    @SuppressWarnings("unused")
+    private static final Logger logger = Logger.getLogger(SimpleExcelTaxonImportState.class);
+
+    private Map<String, Reference> refMap = new HashMap<>();
+
+    private Map<String, TeamOrPersonBase<?>> agentMap = new HashMap<>();
+
+    private final Map<String, Taxon> higherTaxonTaxonMap = new HashMap<String, Taxon>();
+
+    //using titleCache
+    private Map<String, NonViralName<?>> nameMap = new HashMap<>();
+
+
+// ************************* CONSTRUCTUR *******************************/
+    /**
+     * @param config
+     */
+    public SimpleExcelTaxonImportState(CONFIG config) {
+        super(config);
+    }
+
+ //************************ PUTTER / GETTER *****************************/
+    public void putReference(String title, Reference ref){
+        refMap.put(title, ref);
+    }
+    public Reference getReference(String title){
+        return refMap.get(title);
+    }
+
+    public void putAgentBase(String title, TeamOrPersonBase<?> agent){
+        agentMap.put(title, agent);
+    }
+    public TeamOrPersonBase<?> getAgentBase(String title){
+        return agentMap.get(title);
+    }
+
+    //higher taxon
+    public Taxon getHigherTaxon(String higherName) {
+        return higherTaxonTaxonMap.get(higherName);
+    }
+    public Taxon putHigherTaxon(String higherName, Taxon taxon) {
+        return higherTaxonTaxonMap.put(higherName, taxon);
+    }
+    public Taxon removeHigherTaxon(String higherName) {
+        return higherTaxonTaxonMap.remove(higherName);
+    }
+    public boolean containsHigherTaxon(String higherName) {
+        return higherTaxonTaxonMap.containsKey(higherName);
+    }
+
+    //names
+    public void putName(String titleCache, NonViralName<?> name){
+        nameMap.put(titleCache, name);
+    }
+    public NonViralName<?> getName(String titleCache){
+        return nameMap.get(titleCache);
+    }
+
+}