Unifiy name and taxon creation
[cdmlib-apps.git] / app-import / src / main / java / eu / etaxonomy / cdm / io / globis / GlobisImportBase.java
index db71e5d7e6573efa13865ca28dbad3a36c7242c3..87380caec7e316e2111851917f0d02f1235dcfb1 100644 (file)
@@ -1,8 +1,8 @@
 /**\r
 * Copyright (C) 2007 EDIT\r
-* European Distributed Institute of Taxonomy \r
+* European Distributed Institute of Taxonomy\r
 * http://www.e-taxonomy.eu\r
-* \r
+*\r
 * The contents of this file are subject to the Mozilla Public License Version 1.1\r
 * See LICENSE.TXT at the top of this package for the full license terms.\r
 */\r
@@ -19,6 +19,7 @@ import java.util.UUID;
 \r
 import org.apache.commons.lang.StringUtils;\r
 import org.apache.log4j.Logger;\r
+import org.hibernate.NonUniqueObjectException;\r
 import org.joda.time.DateTime;\r
 \r
 import eu.etaxonomy.cdm.io.common.CdmImportBase;\r
@@ -30,6 +31,10 @@ import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
 import eu.etaxonomy.cdm.io.common.Source;\r
 import eu.etaxonomy.cdm.io.common.mapping.DbImportMapping;\r
 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;\r
+import eu.etaxonomy.cdm.model.agent.INomenclaturalAuthor;\r
+import eu.etaxonomy.cdm.model.agent.Person;\r
+import eu.etaxonomy.cdm.model.agent.Team;\r
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;\r
 import eu.etaxonomy.cdm.model.common.AnnotatableEntity;\r
 import eu.etaxonomy.cdm.model.common.Annotation;\r
 import eu.etaxonomy.cdm.model.common.AnnotationType;\r
@@ -37,8 +42,8 @@ import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;\r
 import eu.etaxonomy.cdm.model.common.Language;\r
 import eu.etaxonomy.cdm.model.common.User;\r
-import eu.etaxonomy.cdm.model.location.NamedArea;\r
 import eu.etaxonomy.cdm.model.location.Country;\r
+import eu.etaxonomy.cdm.model.location.NamedArea;\r
 import eu.etaxonomy.cdm.model.name.ZoologicalName;\r
 import eu.etaxonomy.cdm.strategy.exceptions.StringNotParsableException;\r
 import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;\r
@@ -50,41 +55,41 @@ import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
  */\r
 public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImportBase<GlobisImportConfigurator, GlobisImportState> implements ICdmIO<GlobisImportState>, IPartitionedIO<GlobisImportState> {\r
        private static final Logger logger = Logger.getLogger(GlobisImportBase.class);\r
-       \r
+\r
        public static final UUID ID_IN_SOURCE_EXT_UUID = UUID.fromString("23dac094-e793-40a4-bad9-649fc4fcfd44");\r
-       \r
+\r
        //NAMESPACES\r
-       \r
+\r
        protected static final String REFERENCE_NAMESPACE = "Literatur";\r
        protected static final String TAXON_NAMESPACE = "current_species";\r
        protected static final String COLLECTION_NAMESPACE = "Collection";\r
        protected static final String IMAGE_NAMESPACE = "Einzelbilder";\r
        protected static final String SPEC_TAX_NAMESPACE = "specTax";\r
        protected static final String TYPE_NAMESPACE = "specTax.SpecTypeDepository";\r
-       \r
-       private String pluralString;\r
-       private String dbTableName;\r
-       //TODO needed?\r
-       private Class cdmTargetClass;\r
 \r
-       private INonViralNameParser parser = NonViralNameParserImpl.NewInstance();\r
+       private final String pluralString;\r
+       private final String dbTableName;\r
+       private final Class cdmTargetClass;\r
+\r
+       private final INonViralNameParser<?> parser = NonViralNameParserImpl.NewInstance();\r
+\r
 \r
-       \r
        /**\r
         * @param dbTableName\r
-        * @param dbTableName2 \r
+        * @param dbTableName2\r
         */\r
-       public GlobisImportBase(String pluralString, String dbTableName, Class cdmTargetClass) {\r
+       public GlobisImportBase(String pluralString, String dbTableName, Class<?> cdmTargetClass) {\r
                this.pluralString = pluralString;\r
                this.dbTableName = dbTableName;\r
                this.cdmTargetClass = cdmTargetClass;\r
        }\r
 \r
-       protected void doInvoke(GlobisImportState state){\r
+       @Override\r
+    protected void doInvoke(GlobisImportState state){\r
                logger.info("start make " + getPluralString() + " ...");\r
                GlobisImportConfigurator config = state.getConfig();\r
                Source source = config.getSource();\r
-                       \r
+\r
                String strIdQuery = getIdQuery();\r
                String strRecordQuery = getRecordQuery(config);\r
 \r
@@ -98,7 +103,7 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                        logger.error("SQLException:" +  e);\r
                        state.setUnsuccessfull();\r
                }\r
-               \r
+\r
                logger.info("end make " + getPluralString() + " ... " + getSuccessString(true));\r
                return;\r
        }\r
@@ -107,38 +112,133 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
         * @param authorAndYear\r
         * @param zooName\r
         */\r
-       protected void handleAuthorAndYear(String authorAndYear, ZoologicalName zooName, Integer id) {\r
+       protected void handleAuthorAndYear(String authorAndYear, ZoologicalName zooName, Integer id, GlobisImportState state) {\r
                if (isBlank(authorAndYear)){\r
                        return;\r
-               }\r
-               try {\r
-                       String doubtfulAuthorAndYear = null;\r
-                       if(authorAndYear.matches(".+\\,\\s\\[\\d{4}\\].*")){\r
-                               doubtfulAuthorAndYear = authorAndYear;\r
-                               authorAndYear = authorAndYear.replace("[", "").replace("]", "");\r
+               }else if ("[Denis & Schifferm\u00FCller], 1775".equals(authorAndYear)){\r
+                       handleDenisSchiffermueller(zooName, state);\r
+                       return;\r
+               }else{\r
+                       try {\r
+                               String doubtfulAuthorAndYear = null;\r
+                               if(authorAndYear.matches(".+\\,\\s\\[\\d{4}\\].*")){\r
+                                       doubtfulAuthorAndYear = authorAndYear;\r
+                                       authorAndYear = authorAndYear.replace("[", "").replace("]", "");\r
+                               }\r
+\r
+                               parser.parseAuthors(zooName, authorAndYear);\r
+                               deduplicateAuthors(zooName, state);\r
+\r
+                               if (doubtfulAuthorAndYear != null){\r
+                                       zooName.setAuthorshipCache(doubtfulAuthorAndYear, true);\r
+                               }\r
+\r
+                       } catch (StringNotParsableException e) {\r
+                               logger.warn("Author could not be parsed: " + authorAndYear + " for id "  +id);\r
+                               zooName.setAuthorshipCache(authorAndYear, true);\r
                        }\r
-                       if (authorAndYear.contains("?")){\r
-                               authorAndYear = authorAndYear.replace("H?bner", "H\u00fcbner");\r
-                               authorAndYear = authorAndYear.replace("Oberth?r", "Oberth\u00fcr");\r
-                               authorAndYear = authorAndYear.replace("M?n?tri?s","M\u00E9n\u00E9tri\u00E9s");\r
-                               authorAndYear = authorAndYear.replace("Schifferm?ller","Schifferm\u00fcller");\r
-                               \r
-                               //TODO remove\r
-                               authorAndYear = authorAndYear.replace("?", "");\r
-                               \r
+               }\r
+       }\r
+\r
+       /**\r
+        * @param zooName\r
+        * @param state\r
+        */\r
+       private void handleDenisSchiffermueller(ZoologicalName zooName,\r
+                       GlobisImportState state) {\r
+               String teamStr = "Denis & Schifferm\u00FCller";\r
+               Team team = state.getTeam(teamStr);\r
+               if (team == null){\r
+                       team = Team.NewInstance();\r
+                       state.putTeam(teamStr, team);\r
+                       getAgentService().save(team);\r
+               }\r
+               zooName.setCombinationAuthorship(team);\r
+               zooName.setPublicationYear(1775);\r
+               zooName.setAuthorshipCache("[Denis & Schifferm\u00FCller], 1775", true);\r
+       }\r
+\r
+\r
+       private void deduplicateAuthors(ZoologicalName zooName, GlobisImportState state) {\r
+               zooName.setCombinationAuthorship(getExistingAuthor(zooName.getCombinationAuthorship(), state));\r
+               zooName.setExCombinationAuthorship(getExistingAuthor(zooName.getExCombinationAuthorship(), state));\r
+               zooName.setBasionymAuthorship(getExistingAuthor(zooName.getBasionymAuthorship(), state));\r
+               zooName.setExBasionymAuthorship(getExistingAuthor(zooName.getExBasionymAuthorship(), state));\r
+       }\r
+\r
+       private TeamOrPersonBase<?> getExistingAuthor(INomenclaturalAuthor nomAuthor, GlobisImportState state) {\r
+               TeamOrPersonBase<?> author = (TeamOrPersonBase<?>)nomAuthor;\r
+               if (author == null){\r
+                       return null;\r
+               }\r
+               if (author instanceof Person){\r
+                       Person person = state.getPerson(author.getTitleCache());\r
+                       return saveAndDecide(person, author, author.getTitleCache(), state);\r
+               }else if (author instanceof Team){\r
+                       String key = GlobisAuthorImport.makeTeamKey((Team)author, state, getAgentService());\r
+                       Team existingTeam = state.getTeam(key);\r
+                       if (existingTeam == null){\r
+                               Team newTeam = Team.NewInstance();\r
+                               for (Person member :((Team) author).getTeamMembers()){\r
+                                       Person existingPerson = state.getPerson(member.getTitleCache());\r
+                                       if (existingPerson != null){\r
+                                               try {\r
+                                                       getAgentService().update(existingPerson);\r
+                                               } catch (NonUniqueObjectException nuoe){\r
+                                                       // person already exists in\r
+                                                       existingPerson = CdmBase.deproxy(getAgentService().find(existingPerson.getUuid()), Person.class);\r
+                                                       state.putPerson(existingPerson.getTitleCache(), existingPerson);\r
+                                               } catch (Exception e) {\r
+                                                       throw new RuntimeException (e);\r
+                                               }\r
+                                               newTeam.addTeamMember(existingPerson);\r
+//\r
+//                                             logger.warn("newTeam " + newTeam.getId());\r
+                                       }else{\r
+                                               newTeam.addTeamMember(member);\r
+                                       }\r
+                               }\r
+                               author = newTeam;\r
                        }\r
-                       \r
-                       parser.parseAuthors(zooName, authorAndYear);\r
-                       if (doubtfulAuthorAndYear != null){\r
-                               zooName.setAuthorshipCache(doubtfulAuthorAndYear, true);\r
+\r
+                       return saveAndDecide(existingTeam, author, key, state);\r
+               }else{\r
+                       logger.warn("Author type not supported: " + author.getClass().getName());\r
+                       return author;\r
+               }\r
+       }\r
+\r
+       private TeamOrPersonBase<?> saveAndDecide(TeamOrPersonBase<?> existing, TeamOrPersonBase<?> author, String key, GlobisImportState state) {\r
+               if (existing != null){\r
+                       try {\r
+                               getAgentService().update(existing);\r
+                       } catch (NonUniqueObjectException nuoe){\r
+                               // person already exists in\r
+                               existing = CdmBase.deproxy(getAgentService().find(existing.getUuid()), TeamOrPersonBase.class);\r
+                               putAgent(existing, key, state);\r
+                       } catch (Exception e) {\r
+                               throw new RuntimeException (e);\r
                        }\r
-                       \r
-               } catch (StringNotParsableException e) {\r
-                       logger.warn("Author could not be parsed: " + authorAndYear + " for id "  +id);\r
-                       zooName.setAuthorshipCache(authorAndYear, true);\r
+                       return existing;\r
+               }else{\r
+                       getAgentService().save(author);\r
+                       putAgent(author, key, state);\r
+                       return author;\r
+               }\r
+       }\r
+\r
+       /**\r
+        * @param author\r
+        * @param key\r
+        * @param state\r
+        */\r
+       private void putAgent(TeamOrPersonBase<?> agent, String key, GlobisImportState state) {\r
+               if (agent instanceof Team){\r
+                       state.putTeam(key, (Team)agent);\r
+               }else{\r
+                       state.putPerson(key, (Person)agent);\r
                }\r
        }\r
-       \r
 \r
        /**\r
         * @param state\r
@@ -149,7 +249,7 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                NamedArea country = Country.getCountryByLabel(countryStr);\r
                if (country == null){\r
                        try {\r
-                               country = (NamedArea)state.getTransformer().getNamedAreaByKey(countryStr);\r
+                               country = state.getTransformer().getNamedAreaByKey(countryStr);\r
                        } catch (UndefinedTransformerMethodException e) {\r
                                e.printStackTrace();\r
                        }\r
@@ -157,15 +257,16 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                return country;\r
        }\r
 \r
-       \r
 \r
-       public boolean doPartition(ResultSetPartitioner partitioner, GlobisImportState state) {\r
+\r
+       @Override\r
+    public boolean doPartition(ResultSetPartitioner partitioner, GlobisImportState state) {\r
                boolean success = true ;\r
                Set objectsToSave = new HashSet();\r
-               \r
+\r
                DbImportMapping<?, ?> mapping = getMapping();\r
                mapping.initialize(state, cdmTargetClass);\r
-               \r
+\r
                ResultSet rs = partitioner.getResultSet();\r
                try{\r
                        while (rs.next()){\r
@@ -175,21 +276,21 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                        logger.error("SQLException:" +  e);\r
                        return false;\r
                }\r
-       \r
+\r
                partitioner.startDoSave();\r
                getCommonService().save(objectsToSave);\r
                return success;\r
        }\r
 \r
 \r
-       \r
+\r
        /**\r
         * @return\r
         */\r
        protected /*abstract*/ DbImportMapping<?, ?> getMapping(){\r
                return null;\r
        }\r
-       \r
+\r
        /**\r
         * @return\r
         */\r
@@ -202,11 +303,12 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                String result = " SELECT id FROM " + getTableName();\r
                return result;\r
        }\r
-       \r
+\r
        /* (non-Javadoc)\r
         * @see eu.etaxonomy.cdm.io.berlinModel.in.IPartitionedIO#getPluralString()\r
         */\r
-       public String getPluralString(){\r
+       @Override\r
+    public String getPluralString(){\r
                return pluralString;\r
        }\r
 \r
@@ -216,7 +318,7 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
        protected String getTableName(){\r
                return this.dbTableName;\r
        }\r
-       \r
+\r
        protected boolean doIdCreatedUpdatedNotes(GlobisImportState state, IdentifiableEntity identifiableEntity, ResultSet rs, long id, String namespace)\r
                        throws SQLException{\r
                boolean success = true;\r
@@ -226,26 +328,20 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                success &= doCreatedUpdatedNotes(state, identifiableEntity, rs, namespace);\r
                return success;\r
        }\r
-       \r
-       \r
+\r
+\r
        protected boolean doCreatedUpdatedNotes(GlobisImportState state, AnnotatableEntity annotatableEntity, ResultSet rs, String namespace)\r
                        throws SQLException{\r
 \r
                GlobisImportConfigurator config = state.getConfig();\r
                Object createdWhen = rs.getObject("Created_When");\r
                String createdWho = rs.getString("Created_Who");\r
-               Object updatedWhen = null;\r
-               String updatedWho = null;\r
-               try {\r
-                       updatedWhen = rs.getObject("Updated_When");\r
-                       updatedWho = rs.getString("Updated_who");\r
-               } catch (SQLException e) {\r
-                       //Table "Name" has no updated when/who\r
-               }\r
+               Object updatedWhen = rs.getObject("Updated_When");\r
+               String updatedWho = rs.getString("Updated_who");\r
                String notes = rs.getString("notes");\r
-               \r
+\r
                boolean success  = true;\r
-               \r
+\r
                //Created When, Who, Updated When Who\r
                if (config.getEditor() == null || config.getEditor().equals(EDITOR.NO_EDITORS)){\r
                        //do nothing\r
@@ -270,8 +366,8 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                }else {\r
                        logger.warn("Editor type not yet implemented: " + config.getEditor());\r
                }\r
-               \r
-               \r
+\r
+\r
                //notes\r
                if (StringUtils.isNotBlank(notes)){\r
                        String notesString = String.valueOf(notes);\r
@@ -286,13 +382,13 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                }\r
                return success;\r
        }\r
-       \r
+\r
        private User getUser(String userString, GlobisImportState state){\r
-               if (StringUtils.isBlank(userString)){\r
+               if (isBlank(userString)){\r
                        return null;\r
                }\r
                userString = userString.trim();\r
-               \r
+\r
                User user = state.getUser(userString);\r
                if (user == null){\r
                        user = getTransformedUser(userString,state);\r
@@ -305,7 +401,7 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                }\r
                return user;\r
        }\r
-       \r
+\r
        private User getTransformedUser(String userString, GlobisImportState state){\r
                Method method = state.getConfig().getUserTransformationMethod();\r
                if (method == null){\r
@@ -321,19 +417,19 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
        }\r
 \r
        private User makeNewUser(String userString, GlobisImportState state){\r
-               String pwd = getPassword(); \r
+               String pwd = getPassword();\r
                User user = User.NewInstance(userString, pwd);\r
                state.putUser(userString, user);\r
                getUserService().save(user);\r
                logger.info("Added new user: " + userString);\r
                return user;\r
        }\r
-       \r
+\r
        private String getPassword(){\r
                String result = UUID.randomUUID().toString();\r
                return result;\r
        }\r
-       \r
+\r
        private DateTime getDateTime(Object timeString){\r
                if (timeString == null){\r
                        return null;\r
@@ -348,9 +444,9 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                }\r
                return dateTime;\r
        }\r
-       \r
-       \r
-       \r
+\r
+\r
+\r
        /**\r
         * Reads a foreign key field from the result set and adds its value to the idSet.\r
         * @param rs\r
@@ -365,10 +461,10 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                        idSet.add(id);\r
                }\r
        }\r
-       \r
-       \r
-       \r
-       \r
+\r
+\r
+\r
+\r
        /**\r
         * Returns true if i is a multiple of recordsPerTransaction\r
         * @param i\r
@@ -379,12 +475,12 @@ public abstract class GlobisImportBase<CDM_BASE extends CdmBase> extends CdmImpo
                startTransaction();\r
                return (i % recordsPerLoop) == 0;\r
        }\r
-       \r
+\r
        protected void doLogPerLoop(int count, int recordsPerLog, String pluralString){\r
                if ((count % recordsPerLog ) == 0 && count!= 0 ){ logger.info(pluralString + " handled: " + (count));}\r
        }\r
-       \r
 \r
 \r
-       \r
+\r
+\r
 }\r