ref #1447 improve command line merger
authorAndreas Müller <a.mueller@bgbm.org>
Tue, 11 Feb 2020 12:35:43 +0000 (13:35 +0100)
committerAndreas Müller <a.mueller@bgbm.org>
Tue, 11 Feb 2020 12:35:43 +0000 (13:35 +0100)
cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/merging/PesiCommandLineMerge.java
cdm-pesi/src/main/java/eu/etaxonomy/cdm/app/pesi/merging/PesiMergeBase.java

index 8e356c0ca3dedc7fb41bdaa5ca1ae59d53acb3fa..790f742e940cf0493ca5b2338e6a0329c5e04783 100644 (file)
@@ -8,6 +8,8 @@
 */
 package eu.etaxonomy.cdm.app.pesi.merging;
 
+import java.util.HashSet;
+import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.UUID;
@@ -17,6 +19,7 @@ import org.apache.log4j.Logger;
 import org.springframework.transaction.TransactionStatus;
 
 import eu.etaxonomy.cdm.api.service.DeleteResult;
+import eu.etaxonomy.cdm.api.service.config.SynonymDeletionConfigurator;
 import eu.etaxonomy.cdm.api.service.config.TaxonDeletionConfigurator;
 import eu.etaxonomy.cdm.app.common.CdmDestinations;
 import eu.etaxonomy.cdm.common.CdmRegEx;
@@ -25,6 +28,7 @@ import eu.etaxonomy.cdm.database.DbSchemaValidation;
 import eu.etaxonomy.cdm.database.ICdmDataSource;
 import eu.etaxonomy.cdm.io.api.application.CdmIoApplicationController;
 import eu.etaxonomy.cdm.io.common.mapping.out.DbLastActionMapper;
+import eu.etaxonomy.cdm.io.pesi.erms.ErmsTransformer;
 import eu.etaxonomy.cdm.io.pesi.out.PesiTransformer;
 import eu.etaxonomy.cdm.model.common.Annotation;
 import eu.etaxonomy.cdm.model.common.CdmBase;
@@ -40,6 +44,7 @@ import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
 import eu.etaxonomy.cdm.model.taxon.TaxonRelationship;
+import eu.etaxonomy.cdm.model.taxon.TaxonRelationshipType;
 
 /**
  * @author a.mueller
@@ -55,66 +60,243 @@ public class PesiCommandLineMerge extends PesiMergeBase {
 
     private void invoke(ICdmDataSource source){
         app = CdmIoApplicationController.NewInstance(source, DbSchemaValidation.VALIDATE, false);
-
-        while(booleanAnswer("New merge")){
+        doInvoke();
+    }
+    private void doInvoke(){
+        List<List<String>> fileData = null;
+        String next = nextMerge(fileData);
+        while(next.equalsIgnoreCase("m")|| next.equals("f")){
             TransactionStatus tx = app.startTransaction();
-            Taxon[] taxa = null;
-            while (taxa == null) {
-                taxa = readTaxa();
+            TaxonInformation taxonInformation;
+            if (next.equalsIgnoreCase("f")){
+                if (fileData == null){
+                    fileData = getFileData();
+                }else if (fileData.isEmpty()){
+                    fileData = null;
+                    next = nextMerge(fileData);
+                    continue;
+                }
+                taxonInformation = readLineFromFile(fileData);
+                if (taxonInformation == null){
+                    app.rollbackTransaction(tx);
+                    nextMerge(fileData);
+                    continue;
+                }
+            }else{
+                TaxonBase<?>[] taxa = null;
+                while (taxa == null) {
+                    taxa = readTaxa();
+                }
+                taxonInformation = new TaxonInformation();
+                taxonInformation.taxon2 = taxa[0];
+                taxonInformation.taxon1 = taxa[1];
+            }
+
+            try {
+                mergeTaxa(tx, taxonInformation);
+            } catch (Exception e) {
+                e.printStackTrace();
+                app.rollbackTransaction(tx);
+                continue;
             }
-            boolean commit = compareTaxa(taxa);
-            if (commit){
-                moveTaxonInformation(taxa[0],taxa[1]);
+            next = nextMerge(fileData);
+        }
+    }
+
+    private boolean mergeTaxa(TransactionStatus tx, TaxonInformation taxonInformation) {
+        boolean commit = compareTaxa(taxonInformation);
+        if (commit){
+            moveTaxonInformation(taxonInformation);
+        }
+        if (commit){
+            app.commitTransaction(tx);
+            if (taxonInformation.taxonToUse == 1 && taxonInformation.nameToUse == 1){
+                removeTaxon(taxonInformation.taxon2);
+            }else if (booleanAnswer("Information moved. Delete old taxon")){
+                removeTaxon(taxonInformation.taxonToUse == 2 ? taxonInformation.taxon1 : taxonInformation.taxon2);
             }
-            if (commit){
-                app.commitTransaction(tx);
-                if (booleanAnswer("Information moved. Delete old taxon")){
-                    removeTaxon(taxa[0]);
+        }else{
+            app.rollbackTransaction(tx);
+        }
+        return commit;
+    }
+
+    private class TaxonInformation{
+        TaxonBase<?> taxon1;
+        TaxonBase<?> taxon2;
+        int taxonToUse = 1;   //
+        int nameToUse = 1;
+    }
+
+    /**
+     * Reads a line from the file, returns it's taxon information and removes
+     * the line from the input list.
+     */
+    private TaxonInformation readLineFromFile(List<List<String>> fileData) {
+        List<String> line = fileData.get(0);
+        TaxonInformation taxonInformation = new TaxonInformation();
+        taxonInformation.taxon1 = taxonByString(line.get(0));
+        taxonInformation.taxon2 = taxonByString(line.get(1));
+
+        if (taxonInformation.taxon1 == null || taxonInformation.taxon2 == null){
+            boolean cancel = booleanAnswer("Taxon1 or Taxon2 could not be read from DB! Cancel record");
+            if (cancel){
+                fileData.remove(0);
+            }
+            return null;
+        }
+
+        try {
+            Integer taxonToUse = Integer.valueOf(line.get(2));
+            if (1 != taxonInformation.taxonToUse){
+                booleanAnswer("Stay taxon is not '1'");
+            }
+            Integer nameToUse = "".equals(line.get(3))? taxonToUse: Integer.valueOf(line.get(3));
+            if (taxonToUse != 1 && taxonToUse != 2 && taxonToUse != 0){
+                boolean cancel = booleanAnswer("taxonToUse is not 0, 1 or 2. Cancel record");
+                if (cancel){
+                    fileData.remove(0);
                 }
+                return null;
+            }else if (taxonToUse == 0){
+                logger.warn("Record marked as homonym. No merge: " + taxonInformation.taxon1.getName().getNameCache());
+                fileData.remove(0);
+                return null;
             }else{
-                app.rollbackTransaction(tx);
+                taxonInformation.taxonToUse = taxonToUse;
             }
+            if (nameToUse == null){
+                nameToUse = taxonToUse;
+            }
+            if (nameToUse != 1 && nameToUse != 2){
+                logger.warn("Name to use has incorrect value: " +  nameToUse);
+            }else{
+                taxonInformation.nameToUse = nameToUse;
+            }
+        } catch (NumberFormatException e) {
+            e.printStackTrace();
+            taxonInformation = null;
         }
+        fileData.remove(0);
+        return taxonInformation;
     }
 
-    private boolean compareTaxa(Taxon[] taxa) {
-        Taxon removeTaxon = taxa[0];
-        Taxon stayTaxon = taxa[1];
+    private List<List<String>> getFileData() {
+        List<List<String>> result = null;
+        while(result == null){
+            String input = CdmUtils.readInputLine("Path and filename: ");
+            result = readCsvFile(input);
+        }
+        return result;
+    }
+
+    private String nextMerge(List<List<String>> fileData) {
+        if (fileData != null){
+            return "f";
+        }
+        do{
+            String input = CdmUtils.readInputLine("Next input: manual[m], file[f], quit[q]: ");
+            if (input.matches("[mMfFqQ]")){
+                return input;
+            }
+        }while (true);
+    }
+
+    private boolean compareTaxa(TaxonInformation taxonInformation) {
+        TaxonBase<?> removeTaxon = taxonInformation.taxon2;
+        TaxonBase<?> stayTaxon = taxonInformation.taxon1;
         String nc1 = removeTaxon.getName().getNameCache();
         String nc2 = stayTaxon.getName().getNameCache();
 
         String ft1 = removeTaxon.getName().getFullTitleCache();
         String ft2 = stayTaxon.getName().getFullTitleCache();
-        System.out.println("Remove: " + ft1);
-        System.out.println("Stay  : " + ft2);
+        System.out.println("Remove " + getStatusStr(removeTaxon) + ft1);
+        System.out.println("Stay   " + getStatusStr(stayTaxon) + ft2);
+        boolean isStandard = taxonInformation.taxonToUse == 1 && taxonInformation.nameToUse == 1;
         if (!nc1.equals(nc2)){
             return booleanAnswer("Name Cache differs!!! Do you really want to merge???");
         }else if (!ft1.equals(ft2)){
-            return booleanAnswer("Full title cache differs! Do you really want to merge anyway");
+            return isStandard || booleanAnswer("Full title cache differs! Do you really want to merge anyway");
         }else{
-            return booleanAnswer("Same title. Merge");
+            return isStandard || booleanAnswer("Same title. Merge");
         }
     }
 
-    private void removeTaxon(Taxon taxon) {
-        TaxonNode nodeToRemove = taxon.getTaxonNodes().iterator().next();
-        TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();
-        DeleteResult result = app.getTaxonNodeService().deleteTaxonNode(nodeToRemove.getUuid(), config);
+    private String getStatusStr(TaxonBase<?> taxon) {
+        //TODO MAN and Taxon Synonyms
+        if (taxon.isInstanceOf(Synonym.class)){
+            return "Syn: ";
+        }else{
+            return "Acc: ";
+        }
+    }
+
+    private void removeTaxon(TaxonBase<?> taxonBase) {
+        DeleteResult result;
+        if (taxonBase.isInstanceOf(Taxon.class)){
+            Taxon taxonToRemove = CdmBase.deproxy(taxonBase, Taxon.class);
+            TaxonDeletionConfigurator config = new TaxonDeletionConfigurator();
+            if (isTaxonSynonym(taxonToRemove)){
+                result = app.getTaxonService().deleteTaxon(taxonToRemove.getUuid(), config, null);
+            }else{
+                TaxonNode nodeToRemove = taxonToRemove.getTaxonNodes().iterator().next();
+                result = app.getTaxonNodeService().deleteTaxonNode(nodeToRemove.getUuid(), config);
+            }
+        }else{
+            Synonym syn = CdmBase.deproxy(taxonBase, Synonym.class);
+            SynonymDeletionConfigurator config = new SynonymDeletionConfigurator();
+            result = app.getTaxonService().deleteSynonym(syn.getUuid(), config);
+        }
         if (!result.isOk()){
             System.out.println("Remove taxon was not successful.");
         }
     }
 
     private boolean booleanAnswer(String message) {
-        String answer = CdmUtils.readInputLine(message + " (y/n)? ");
+        String answer = "";
+        while (!(answer.equalsIgnoreCase("y") || answer.equalsIgnoreCase("n"))){
+            answer = CdmUtils.readInputLine(message + " (y/n)? ");
+        }
         return answer.equalsIgnoreCase("y");
     }
 
-    private boolean moveTaxonInformation(Taxon removeTaxon, Taxon stayTaxon) {
+    private boolean moveTaxonInformation(TaxonInformation taxonInformation) {
         try {
+
+            TaxonBase<?> removeTaxon = CdmBase.deproxy(taxonInformation.taxonToUse == 2 ? taxonInformation.taxon1: taxonInformation.taxon2);
+            TaxonBase<?> stayTaxon = CdmBase.deproxy(taxonInformation.taxonToUse == 2 ? taxonInformation.taxon2 : taxonInformation.taxon1);
+
+            //mergeTaxa;
+            mergeSources(removeTaxon, stayTaxon);
+            mergeAnnotations(removeTaxon, stayTaxon);
+            mergeMarkers(removeTaxon, stayTaxon);
+            //TODO for
+            mergeExtensions(removeTaxon, stayTaxon);
+            mergeCredits(removeTaxon, stayTaxon);
+            if (removeTaxon.isInstanceOf(Taxon.class)){
+                Taxon removeAccTaxon = CdmBase.deproxy(removeTaxon, Taxon.class);
+
+                Taxon stayAccTaxon = accTaxon(stayTaxon);
+                mergeDescriptions(removeAccTaxon, accTaxon(stayTaxon));
+                boolean isTaxonSynonym = isTaxonSynonym(removeAccTaxon);
+                mergeSynonyms(removeAccTaxon, stayAccTaxon, isTaxonSynonym);
+                mergeChildren(removeAccTaxon, stayAccTaxon, isTaxonSynonym);
+                //TODO taxon synonym relations
+                mergeTaxonRelations(removeAccTaxon, stayAccTaxon, isTaxonSynonym);
+            }
+
             //mergeNames;
-            TaxonName removeName = CdmBase.deproxy(removeTaxon.getName());
-            TaxonName stayName = CdmBase.deproxy(stayTaxon.getName());
+            TaxonName removeName;
+            TaxonName stayName;
+            if (taxonInformation.nameToUse == taxonInformation.taxonToUse){
+                removeName = CdmBase.deproxy(removeTaxon.getName());
+                stayName = CdmBase.deproxy(stayTaxon.getName());
+            }else{
+                removeName = CdmBase.deproxy(stayTaxon.getName());
+                stayName = CdmBase.deproxy(removeTaxon.getName());
+                stayTaxon.setName(stayName);
+            }
+            //TODO unclear if name information should be merged at all
             mergeSources(removeName, stayName);
             mergeAnnotations(removeName, stayName);
             mergeMarkers(removeName, stayName);
@@ -124,24 +306,44 @@ public class PesiCommandLineMerge extends PesiMergeBase {
             mergeHybridRelationships(removeName, stayName);
             mergeNameDescriptions(removeName, stayName);
 
-            //mergeTaxa;
-            mergeSources(removeTaxon, stayTaxon);
-            mergeAnnotations(removeTaxon, stayTaxon);
-            mergeMarkers(removeTaxon, stayTaxon);
-            mergeExtensions(removeTaxon, stayTaxon);
-            mergeCredits(removeTaxon, stayTaxon);
-            mergeDescriptions(removeTaxon, stayTaxon);
-            mergeSynonyms(removeTaxon, stayTaxon);
-            mergeChildren(removeTaxon, stayTaxon);
-            mergeTaxonRelations(removeTaxon, stayTaxon);
-            return booleanAnswer("Commit moved information");
+            if(taxonInformation.taxonToUse == 1 && taxonInformation.nameToUse == 1){
+                return true;
+            }else{
+                return booleanAnswer("Commit moved information");
+            }
         } catch (CloneNotSupportedException e) {
             e.printStackTrace();
             return false;
         }
     }
 
-    private void mergeTaxonRelations(Taxon removeTaxon, Taxon stayTaxon) {
+    private boolean isTaxonSynonym(Taxon removeAccTaxon) {
+        for (TaxonRelationship rel:  removeAccTaxon.getRelationsFromThisTaxon()){
+            boolean isPseudo = TaxonRelationshipType.pseudoTaxonUuids().contains(rel.getType().getUuid());
+            if (isPseudo){
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private Taxon accTaxon(TaxonBase<?> stayTaxon) {
+        if (stayTaxon.isInstanceOf(Synonym.class)){
+            return CdmBase.deproxy(stayTaxon, Synonym.class).getAcceptedTaxon();
+        }else{
+            return CdmBase.deproxy(stayTaxon, Taxon.class);
+        }
+    }
+
+    private boolean mergeTaxonRelations(Taxon removeTaxon, Taxon stayTaxon, boolean isTaxonSynonym) {
+        if (isTaxonSynonym){
+            if (!removeTaxon.getRelationsToThisTaxon().isEmpty()){
+                logger.warn("taxon synonym has taxon relations to itself. This should not happen. Handle manually.");
+                return false;
+            }else{
+                return true;
+            }
+        }
         for (TaxonRelationship rel : removeTaxon.getRelationsToThisTaxon()){
             System.out.println("Move taxon relationship: " + rel.getType().getTitleCache() + ": " + rel.getFromTaxon().getTitleCache());
 
@@ -156,6 +358,7 @@ public class PesiCommandLineMerge extends PesiMergeBase {
         if(!removeTaxon.getRelationsFromThisTaxon().isEmpty()){
             logger.warn("Taxon-from-relations not yet implemented");
         }
+        return true;
     }
 
     private void mergeNameDescriptions(TaxonName removeName, @SuppressWarnings("unused") TaxonName stayName) {
@@ -179,7 +382,15 @@ public class PesiCommandLineMerge extends PesiMergeBase {
         }
     }
 
-    private void mergeChildren(Taxon removeTaxon, Taxon stayTaxon) {
+    private boolean mergeChildren(Taxon removeTaxon, Taxon stayTaxon, boolean isTaxonSynonym) {
+        if (isTaxonSynonym){
+            if (!removeTaxon.getTaxonNodes().isEmpty()){
+                logger.warn("taxon synonym has taxon node itself. This should not happen. Handle manually.");
+                return false;
+            }else{
+                return true;
+            }
+        }
         TaxonNode removeNode = removeTaxon.getTaxonNodes().iterator().next();
         TaxonNode stayNode = stayTaxon.getTaxonNodes().iterator().next();
         Set<UUID> removeNodeChildrenUuids = removeNode.getChildNodes()
@@ -189,19 +400,32 @@ public class PesiCommandLineMerge extends PesiMergeBase {
             app.getTaxonNodeService().moveTaxonNodes(removeNodeChildrenUuids,
                     stayNode.getUuid(), 0, null);
             System.out.println("Child nodes moved: " + removeNodeChildrenUuids.size());
-
         }
+        return true;
     }
 
-    private void mergeSynonyms(Taxon removeTaxon, Taxon stayTaxon) {
+    private boolean mergeSynonyms(Taxon removeTaxon, Taxon stayTaxon, boolean isTaxonSynonym) {
+        if (isTaxonSynonym){
+            if (!removeTaxon.getSynonyms().isEmpty()){
+                logger.warn("taxon synonym has synonyms itself. This should not happen. Handle manually.");
+                return false;
+            }else{
+                return true;
+            }
+        }
+        Set<Synonym> synonymsToAdd = new HashSet<>();
         for (Synonym synonym : removeTaxon.getSynonyms()){
             if (!synonymExists()){
                 //TODO homotypical group
-                stayTaxon.addSynonym(synonym, synonym.getType());
+                synonymsToAdd.add(synonym);
             }else{
                 //TODO merge synonym names
             }
         }
+        for (Synonym synonym: synonymsToAdd){
+            stayTaxon.addSynonym(synonym, synonym.getType());
+        }
+        return true;
     }
 
     private boolean synonymExists() {
@@ -228,11 +452,45 @@ public class PesiCommandLineMerge extends PesiMergeBase {
 
     private void mergeExtensions(IdentifiableEntity<?> removeEntity,
             IdentifiableEntity<?> stayEntity) throws CloneNotSupportedException {
+
         String className = removeEntity.getClass().getSimpleName();
         for (Extension extension: removeEntity.getExtensions()){
-            System.out.println("Move "+className+" extension: " + extension.getType().getTitleCache() + ": " + extension.getValue());
-            stayEntity.addExtension((Extension)extension.clone());
+            if (!filterExtension(extension, removeEntity, stayEntity)){
+                System.out.println("Move "+className+" extension: " + extension.getType().getTitleCache() + ": " + extension.getValue());
+
+                IdentifiableEntity<?> thisStayEntity = selectStay(removeEntity, stayEntity, "Extension");
+                if (thisStayEntity != null){
+                    thisStayEntity.addExtension((Extension)extension.clone());
+                }
+            }
+        }
+    }
+
+    private IdentifiableEntity<?> selectStay(IdentifiableEntity<?> removeEntity, IdentifiableEntity<?> stayEntity, String type) {
+        if(removeEntity.isInstanceOf(Taxon.class) && stayEntity.isInstanceOf(Synonym.class)){
+            String answer = "";
+            while(!(answer.matches("[sSaAcC]"))){
+                answer = CdmUtils.readInputLine(type + ": Stay is Synonym. Move information to [s]ynonym, to [a]ccepted or [c]ancel extension merge?: ");
+            }
+            if (answer.equalsIgnoreCase("c")){
+                return null;
+            }else if (answer.equalsIgnoreCase("a")){
+               return accTaxon(CdmBase.deproxy(stayEntity, Synonym.class));
+            }else{
+                return stayEntity;
+            }
         }
+        return stayEntity;
+    }
+
+    private boolean filterExtension(Extension extension,
+            @SuppressWarnings("unused") IdentifiableEntity<?> removeEntity,
+            @SuppressWarnings("unused") IdentifiableEntity<?> stayEntity) {
+        if (extension.getType().getUuid().equals(ErmsTransformer.uuidExtDisplayName)){
+            //for merged taxa display name information is not relevant because name is formatted according to "stay" taxon.
+            return true;
+        }
+        return false;
     }
 
     private void mergeMarkers(IdentifiableEntity<?> removeEntity,
@@ -241,7 +499,10 @@ public class PesiCommandLineMerge extends PesiMergeBase {
         for (Marker marker: removeEntity.getMarkers()){
             if (!filterMarker(marker, removeEntity, stayEntity)){
                 System.out.println("Move "+className+" marker: " + marker.getMarkerType().getTitleCache() + ": " + marker.getValue());
-                stayEntity.addMarker((Marker)marker.clone());
+                IdentifiableEntity<?> thisStayEntity = selectStay(removeEntity, stayEntity, "Marker");
+                if (thisStayEntity != null){
+                    thisStayEntity.addMarker((Marker)marker.clone());
+                }
             }
         }
     }
@@ -251,7 +512,8 @@ public class PesiCommandLineMerge extends PesiMergeBase {
         String className = removeEntity.getClass().getSimpleName();
         for (Annotation annotation: removeEntity.getAnnotations()){
             if (!filterAnnotation(annotation, removeEntity, stayEntity)){
-                System.out.println("Move "+className+" note: " + annotation.getAnnotationType().getTitleCache() + ": " + annotation.getText());
+                String type = annotation.getAnnotationType() == null? "no type" : annotation.getAnnotationType().getTitleCache();
+                System.out.println("Move "+className+" note: " + type + ": " + annotation.getText());
                 handleRemoveAnnotation(annotation, removeEntity, stayEntity);
                 stayEntity.addAnnotation((Annotation)annotation.clone());
             }
@@ -280,8 +542,9 @@ public class PesiCommandLineMerge extends PesiMergeBase {
     }
 
     private boolean isLastActionDateAnnotation(Annotation annotation) {
-        return annotation.getAnnotationType().getUuid().equals(DbLastActionMapper.uuidAnnotationTypeLastActionDate)
-            && !isBlank(annotation.getText());
+        return annotation.getAnnotationType()!= null
+                && annotation.getAnnotationType().getUuid().equals(DbLastActionMapper.uuidAnnotationTypeLastActionDate)
+                && !isBlank(annotation.getText());
     }
 
     private void handleRemoveAnnotation(Annotation annotation,
@@ -293,7 +556,7 @@ public class PesiCommandLineMerge extends PesiMergeBase {
                 stayEntity.removeMarker(noLastActionMarker.get());
                 System.out.println("  NoLastActionDate annotation removed from 'stay' " + stayEntity.getClass().getSimpleName());
             }
-        };
+        }
     }
 
     private boolean isNoLastActionMarker(Marker marker) {
@@ -306,37 +569,49 @@ public class PesiCommandLineMerge extends PesiMergeBase {
         return false;
     }
 
-    private Taxon[] readTaxa() {
-
-        try {
-            Taxon taxon1 = readTaxon("Taxon to be removed");
-            Taxon taxon2 = readTaxon("Taxon to stay");
-            return new Taxon[]{taxon1, taxon2};
-        } catch (Exception e) {
-            System.out.println("Reading taxon not successful");
+    private TaxonBase<?>[] readTaxa() {
+        TaxonBase<?> taxon1 = readTaxon("Taxon to be removed");
+        TaxonBase<?> taxon2 = readTaxon("Taxon to stay");
+        if (taxon1 == null || taxon2 == null){
             return null;
+        }else{
+            return new TaxonBase<?>[]{taxon1, taxon2};
         }
     }
 
-    private Taxon readTaxon(String message) {
-        String strTaxon = CdmUtils.readInputLine(message + ": ");
-        TaxonBase<?> taxon;
-        if (strTaxon.matches("\\d{1,10}")){
-            taxon = app.getTaxonService().find(Integer.valueOf(strTaxon));
-        }else if (strTaxon.matches(CdmRegEx.UUID_RE)){
-            taxon = app.getTaxonService().find(UUID.fromString(strTaxon));
-        }else{
-            throw new IllegalArgumentException("Input not recognized as id or uuid.");
+    private TaxonBase<?> readTaxon(String message) {
+        TaxonBase<?> taxon = null;
+        boolean quit = false;
+        while (taxon == null && quit == false){
+            String strTaxon = CdmUtils.readInputLine(message + ": ");
+            if (strTaxon.equalsIgnoreCase("q")){
+                quit = true;
+            }else{
+                taxon = taxonByString(strTaxon);
+            }
         }
         if (taxon == null){
-            throw new IllegalArgumentException("Input was not a valid taxon id.");
+            return null;
         }else if (taxon.isInstanceOf(Synonym.class)){
-            throw new IllegalArgumentException("Input was synonym but accepted taxon required.");
+            return CdmBase.deproxy(taxon, Synonym.class);
         }else{
             return CdmBase.deproxy(taxon, Taxon.class);
         }
     }
 
+    /**
+     * Reads a taxon from database using it's id or uuid as String
+     */
+    private TaxonBase<?> taxonByString(String strTaxon) {
+        TaxonBase<?> taxon = null;
+        if (strTaxon.matches("\\d{1,10}")){
+            taxon = app.getTaxonService().find(Integer.valueOf(strTaxon));
+        }else if (strTaxon.matches(CdmRegEx.UUID_RE)){
+            taxon = app.getTaxonService().find(UUID.fromString(strTaxon));
+        }
+        return taxon;
+    }
+
 
 
     public static void main(String[] args) {
index 24a9acc13550da68441d8e2317fb0277d76b859b..05168b82f4f40c8dee38714acf6a8f9fb337d8a9 100644 (file)
@@ -29,7 +29,7 @@ public abstract class PesiMergeBase {
     protected static List<List<String>> readCsvFile(String fileName){
         List<List<String>> result = new ArrayList<>();
         try {
-            CSVReader reader = new CSVReader(new FileReader(fileName));
+            CSVReader reader = new CSVReader(new FileReader(fileName), ';');
             String[] row;
             while ((row = reader.readNext()) != null){
                 result.add(Arrays.asList(row));
@@ -37,6 +37,7 @@ public abstract class PesiMergeBase {
             reader.close();
         } catch (IOException e1) {
             e1.printStackTrace();
+            return null;
         }
         return result;
     }