fix #9617 rename ICNB to ICNP in cdmlib
[cdmlib.git] / cdmlib-io / src / main / java / eu / etaxonomy / cdm / io / taxonx2013 / TaxonXTreatmentExtractor.java
index 1e0fd9bd3f37737e8f95ef33a1c81970f8735e57..17be14a2c5e0847c88ba4739ffbe3bf5f7582829 100644 (file)
@@ -1,4 +1,3 @@
-// $Id$
 /**
  * Copyright (C) 2013 EDIT
  * European Distributed Institute of Taxonomy
@@ -13,13 +12,14 @@ import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.net.URI;
 import java.util.ArrayList;
+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 java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
 import javax.xml.transform.TransformerException;
@@ -34,53 +34,54 @@ import com.ibm.lsid.MalformedLSIDException;
 
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
 import eu.etaxonomy.cdm.api.service.pager.Pager;
+import eu.etaxonomy.cdm.common.URI;
 import eu.etaxonomy.cdm.model.agent.AgentBase;
 import eu.etaxonomy.cdm.model.agent.Person;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
 import eu.etaxonomy.cdm.model.common.LSID;
 import eu.etaxonomy.cdm.model.common.Language;
-import eu.etaxonomy.cdm.model.common.OriginalSourceType;
-import eu.etaxonomy.cdm.model.common.UuidAndTitleCache;
 import eu.etaxonomy.cdm.model.description.Feature;
-import eu.etaxonomy.cdm.model.description.FeatureNode;
-import eu.etaxonomy.cdm.model.description.FeatureTree;
 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
 import eu.etaxonomy.cdm.model.description.TaxonDescription;
 import eu.etaxonomy.cdm.model.description.TaxonNameDescription;
 import eu.etaxonomy.cdm.model.description.TextData;
-import eu.etaxonomy.cdm.model.name.BacterialName;
-import eu.etaxonomy.cdm.model.name.BotanicalName;
+import eu.etaxonomy.cdm.model.name.INonViralName;
 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.name.ZoologicalName;
+import eu.etaxonomy.cdm.model.name.TaxonName;
 import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationType;
+import eu.etaxonomy.cdm.model.reference.OriginalSourceType;
 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.SynonymType;
 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.term.TermNode;
+import eu.etaxonomy.cdm.model.term.TermTree;
+import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
 import eu.etaxonomy.cdm.persistence.query.MatchMode;
 import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
 import eu.etaxonomy.cdm.strategy.parser.INonViralNameParser;
 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
+import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImplRegExBase;
 
 /**
  * @author pkelbert
- * @date 2 avr. 2013
+ * @since 2 avr. 2013
  *
  */
 public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
-    private static final Logger logger = Logger.getLogger(TaxonXTreatmentExtractor.class);
+    private static final String PUBLICATION_YEAR = "publicationYear";
+
+       private static final Logger logger = Logger.getLogger(TaxonXTreatmentExtractor.class);
 
     private static final String notMarkedUp = "Not marked-up";
     private static final UUID proIbioTreeUUID = UUID.fromString("2c49f506-c7f7-44de-a8b9-2e695de3769c");
@@ -93,7 +94,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
     private  String treatmentMainName,originalTreatmentName;
 
-    private final HashMap<String,Map<String,String>> namesMap = new HashMap<String, Map<String,String>>();
+    private final HashMap<String,Map<String,String>> namesMap = new HashMap<>();
 
 
     private final Pattern keypattern = Pattern.compile("^(\\d+.*|-\\d+.*)");
@@ -104,7 +105,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
     private MyName currentMyName;
 
-    private Reference<?> sourceUrlRef;
+    private Reference sourceUrlRef;
+
+    private String followingText;  //text element immediately following a tax:name in tax:nomenclature TODO move do state
+    private String usedFollowingTextPrefix; //the part of the following text which has been used during taxon name creation
 
     private final TaxonXAddSources sourceHandler = new TaxonXAddSources();
 
@@ -115,11 +119,11 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param configState
      */
     public TaxonXTreatmentExtractor(NomenclaturalCode nomenclaturalCode, Classification classification, TaxonXImport importer,
-            TaxonXImportState configState,Map<String, Feature> featuresMap,  Reference<?> urlSource ) {
+            TaxonXImportState configState,Map<String, Feature> featuresMap,  Reference urlSource) {
         this.nomenclaturalCode=nomenclaturalCode;
         this.classification = classification;
         this.importer=importer;
-        this.configState=configState;
+        this.state2=configState;
         this.featuresMap=featuresMap;
         this.sourceUrlRef =urlSource;
         prepareCollectors(configState, importer.getAgentService());
@@ -136,158 +140,27 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param sourceName: the URI of the document
      */
     @SuppressWarnings({ "rawtypes", "unused" })
-    protected void extractTreatment(Node treatmentnode, List<Object> tosave, Reference<?> refMods, URI sourceName) {
-        logger.info("extractTreatment");
-        List<TaxonNameBase> nametosave = new ArrayList<TaxonNameBase>();
+
+    protected void extractTreatment(Node treatmentnode, Reference refMods, URI sourceName) {        logger.info("extractTreatment");
+        List<TaxonName> namesToSave = new ArrayList<>();
         NodeList children = treatmentnode.getChildNodes();
         Taxon acceptedTaxon =null;
-        Taxon defaultTaxon =null;
-        boolean refgroup=false;
+        boolean hasRefgroup=false;
 
+        //needed?
         for (int i=0;i<children.getLength();i++){
             if(children.item(i).getNodeName().equalsIgnoreCase("tax:ref_group")) {
-                refgroup=true;
+               hasRefgroup=true;
             }
         }
 
         for (int i=0;i<children.getLength();i++){
-
-            if (children.item(i).getNodeName().equalsIgnoreCase("tax:nomenclature")){
-                NodeList nomenclature = children.item(i).getChildNodes();
-                boolean containsName=false;
-                for(int k=0;k<nomenclature.getLength();k++){
-                    if(nomenclature.item(k).getNodeName().equalsIgnoreCase("tax:name")){
-                        containsName=true;
-                        break;
-                    }
-                }
-                if (containsName){
-                    reloadClassification();
-                    //extract "main" the scientific name
-                    try{
-                        acceptedTaxon = extractNomenclature(children.item(i),nametosave,refMods);
-                    }catch(ClassCastException e){e.printStackTrace();System.exit(0);}
-                    //                    System.out.println("acceptedTaxon : "+acceptedTaxon);
-                }
-            }
-            else if (children.item(i).getNodeName().equalsIgnoreCase("tax:ref_group") && maxRankRespected){
-                reloadClassification();
-                //extract the References within the document
-                extractReferences(children.item(i),nametosave,acceptedTaxon,refMods);
-            }
-            else if (children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("multiple") && maxRankRespected){
-                File file = new File("/home/pkelbert/Bureau/multipleTaxonX.txt");
-                FileWriter writer;
-                try {
-                    writer = new FileWriter(file ,true);
-                    writer.write(sourceName+"\n");
-                    writer.flush();
-                    writer.close();
-                } catch (IOException e1) {
-                    // TODO Auto-generated catch block
-                    e1.printStackTrace();
-                }
-                //                String multiple = askMultiple(children.item(i));
-                String multiple = "Other";
-                if (multiple.equalsIgnoreCase("other")) {
-                    extractSpecificFeatureNotStructured(children.item(i),acceptedTaxon, defaultTaxon,nametosave, refMods,multiple);
-                }
-                else
-                    if (multiple.equalsIgnoreCase("synonyms")) {
-                        try{
-                            extractSynonyms(children.item(i),acceptedTaxon, refMods);
-                        }catch(NullPointerException e){
-                            logger.warn("the accepted taxon is maybe null");
-                        }
-                    }
-                    else
-                        if(multiple.equalsIgnoreCase("material examined")){
-                            extractMaterials(children.item(i),acceptedTaxon, refMods, nametosave);
-                        }
-                        else
-                            if (multiple.equalsIgnoreCase("distribution")){
-                                extractDistribution(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods);
-                            }
-                            else
-                                if (multiple.equalsIgnoreCase("type status")){
-                                    extractDescriptionWithReference(children.item(i),acceptedTaxon,defaultTaxon,refMods, "TypeStatus");
-                                }
-                                else
-                                    if (multiple.equalsIgnoreCase("vernacular name")){
-                                        extractDescriptionWithReference(children.item(i),acceptedTaxon,defaultTaxon,refMods, Feature.COMMON_NAME().getTitleCache());
-
-                                    }
-                                    else{
-                                        extractSpecificFeature(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods,multiple);
-                                    }
-
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("biology_ecology") && maxRankRespected){
-                extractFeature(children.item(i),acceptedTaxon,defaultTaxon, nametosave, refMods, Feature.BIOLOGY_ECOLOGY());
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("vernacularName") && maxRankRespected){
-                extractDescriptionWithReference(children.item(i),acceptedTaxon,defaultTaxon,refMods, Feature.COMMON_NAME().getTitleCache());
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("description") && maxRankRespected){
-                extractFeature(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods, Feature.DESCRIPTION());
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("diagnosis") && maxRankRespected){
-                extractFeature(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods,Feature.DIAGNOSIS());
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("discussion") && maxRankRespected){
-                extractFeature(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods, Feature.DISCUSSION());
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("note") && maxRankRespected){
-                extractFeature(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods, Feature.DESCRIPTION());
-            }
-
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("distribution") && maxRankRespected){
-                extractDistribution(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods);
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("etymology") && maxRankRespected){
-                extractFeature(children.item(i),acceptedTaxon,defaultTaxon,nametosave,refMods,Feature.ETYMOLOGY());
-            }
-
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("materials_examined") && maxRankRespected){
-                extractMaterials(children.item(i),acceptedTaxon, refMods, nametosave);
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:figure") && maxRankRespected){
-                extractSpecificFeature(children.item(i),acceptedTaxon,defaultTaxon, nametosave, refMods, "Figure");
-            }
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("Other") && maxRankRespected){
-                extractSpecificFeature(children.item(i),acceptedTaxon,defaultTaxon, nametosave, refMods, "table");
-            }
-
-            else if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
-                    children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("key") && maxRankRespected){
-                //TODO IGNORE keys for the moment
-                //extractKey(children.item(i),acceptedTaxon, nametosave,source, refMods);
-                extractSpecificFeatureNotStructured(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods,"Keys - unparsed");
-            }
-            else{
-                if (!children.item(i).getNodeName().equalsIgnoreCase("tax:pb")){
-                    //logger.info("ANOTHER KIND OF NODES: "+children.item(i).getNodeName()+", "+children.item(i).getAttributes());
-                    if (children.item(i).getAttributes() !=null) {
-                        //logger.info(children.item(i).getAttributes().item(0));
-                    }
-                    extractSpecificFeatureNotStructured(children.item(i),acceptedTaxon,defaultTaxon,nametosave, refMods,notMarkedUp);
-                }
-            }
+               Node child = children.item(i);
+               acceptedTaxon = handleSingleNode(refMods, sourceName, namesToSave, child, acceptedTaxon);
         }
         //        logger.info("saveUpdateNames");
         if (maxRankRespected){
-            importer.getNameService().saveOrUpdate(nametosave);
+            importer.getNameService().saveOrUpdate(namesToSave);
             importer.getClassificationService().saveOrUpdate(classification);
             //logger.info("saveUpdateNames-ok");
         }
@@ -295,6 +168,133 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         buildFeatureTree();
     }
 
+       private Taxon handleSingleNode(Reference refMods, URI sourceName,
+                       List<TaxonName> namesToSave, Node child, Taxon acceptedTaxon) {
+               Taxon defaultTaxon =null;
+
+               String nodeName = child.getNodeName();
+               if (nodeName.equalsIgnoreCase("tax:nomenclature")){
+                   NodeList nomenclatureChildren = child.getChildNodes();
+                   boolean containsName = false;
+                   for(int k=0; k<nomenclatureChildren.getLength(); k++){
+                       if(nomenclatureChildren.item(k).getNodeName().equalsIgnoreCase("tax:name")){
+                           containsName=true;
+                           break;
+                       }
+                   }
+                   if (containsName){
+                       reloadClassification();
+                       //extract "main" the scientific name
+                       try{
+                           acceptedTaxon = extractNomenclature(child, namesToSave, refMods);
+                       }catch(ClassCastException e){
+                               //FIXME exception handling
+                               e.printStackTrace();
+                       }
+                       //                    System.out.println("acceptedTaxon : "+acceptedTaxon);
+                   }
+               }else if (nodeName.equalsIgnoreCase("tax:ref_group") && maxRankRespected){
+                   reloadClassification();
+                   //extract the References within the document
+                   extractReferences(child, namesToSave ,acceptedTaxon,refMods);
+               }else if (nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("multiple") && maxRankRespected){
+                   File file = new File(TaxonXImport.LOG_FOLDER + "multipleTaxonX.txt");
+                   FileWriter writer;
+                   try {
+                       writer = new FileWriter(file ,true);
+                       writer.write(sourceName+"\n");
+                       writer.flush();
+                       writer.close();
+                   } catch (IOException e1) {
+                       // TODO Auto-generated catch block
+                       logger.error(e1.getMessage());
+                   }
+                   //                String multiple = askMultiple(children.item(i));
+                   String multiple = "Other";
+                   if (multiple.equalsIgnoreCase("other")) {
+                       extractSpecificFeatureNotStructured(child,acceptedTaxon, defaultTaxon,namesToSave, refMods,multiple);
+                   }else if (multiple.equalsIgnoreCase("synonyms")) {
+                       try{
+                           extractSynonyms(child,acceptedTaxon, refMods, null);
+                       }catch(NullPointerException e){
+                           logger.warn("the accepted taxon is maybe null");
+                       }
+                   }else if(multiple.equalsIgnoreCase("material examined")){
+                       extractMaterials(child, acceptedTaxon, refMods, namesToSave);
+                   }else if (multiple.equalsIgnoreCase("distribution")){
+                       extractDistribution(child, acceptedTaxon, defaultTaxon, namesToSave, refMods);
+                   }else if (multiple.equalsIgnoreCase("type status")){
+                       extractDescriptionWithReference(child, acceptedTaxon, defaultTaxon,refMods, "TypeStatus");
+                   }else if (multiple.equalsIgnoreCase("vernacular name")){
+                       extractDescriptionWithReference(child, acceptedTaxon, defaultTaxon,refMods, Feature.COMMON_NAME().getTitleCache());
+                   }else{
+                       extractSpecificFeature(child,acceptedTaxon,defaultTaxon,namesToSave, refMods,multiple);
+                   }
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("biology_ecology") && maxRankRespected){
+                   extractFeature(child,acceptedTaxon,defaultTaxon, namesToSave, refMods, Feature.BIOLOGY_ECOLOGY());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("vernacularName") && maxRankRespected){
+                   extractDescriptionWithReference(child, acceptedTaxon,defaultTaxon,refMods, Feature.COMMON_NAME().getTitleCache());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("description") && maxRankRespected){
+                   extractFeature(child,acceptedTaxon,defaultTaxon,namesToSave, refMods, Feature.DESCRIPTION());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("diagnosis") && maxRankRespected){
+                   extractFeature(child,acceptedTaxon,defaultTaxon,namesToSave, refMods,Feature.DIAGNOSIS());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("discussion") && maxRankRespected){
+                   extractFeature(child,acceptedTaxon,defaultTaxon,namesToSave, refMods, Feature.DISCUSSION());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("note") && maxRankRespected){
+                   extractFeature(child,acceptedTaxon,defaultTaxon,namesToSave, refMods, Feature.DESCRIPTION());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("distribution") && maxRankRespected){
+                   extractDistribution(child,acceptedTaxon,defaultTaxon,namesToSave, refMods);
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("etymology") && maxRankRespected){
+                   extractFeature(child,acceptedTaxon,defaultTaxon,namesToSave,refMods,Feature.ETYMOLOGY());
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("materials_examined") && maxRankRespected){
+                   extractMaterials(child,acceptedTaxon, refMods, namesToSave);
+               }
+               else if(nodeName.equalsIgnoreCase("tax:figure") && maxRankRespected){
+                   extractSpecificFeature(child,acceptedTaxon,defaultTaxon, namesToSave, refMods, "Figure");
+               }
+               else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("Other") && maxRankRespected){
+                   extractSpecificFeature(child, acceptedTaxon,defaultTaxon, namesToSave, refMods, "table");
+               }else if(nodeName.equalsIgnoreCase("tax:div") &&
+                               child.getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("key") && maxRankRespected){
+                   //TODO IGNORE keys for the moment
+                   //extractKey(children.item(i),acceptedTaxon, nameToSave,source, refMods);
+                   extractSpecificFeatureNotStructured(child,acceptedTaxon,defaultTaxon,namesToSave, refMods,"Keys - unparsed");
+               }
+               else{
+                   if (! nodeName.equalsIgnoreCase("tax:pb")){
+                       //logger.info("ANOTHER KIND OF NODES: "+children.item(i).getNodeName()+", "+children.item(i).getAttributes());
+                       if (child.getAttributes() !=null) {
+                           logger.info("First Attribute: " + child.getAttributes().item(0));
+                       }
+                       extractSpecificFeatureNotStructured(child,acceptedTaxon,defaultTaxon,namesToSave, refMods, notMarkedUp);
+                   }else{
+                       //FIXME
+                       logger.warn("Unhandled");
+                   }
+               }
+               return acceptedTaxon;
+       }
+
 
     protected Map<String,Feature> getFeaturesUsed(){
         return featuresMap;
@@ -304,25 +304,25 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
     private void buildFeatureTree() {
         logger.info("buildFeatureTree");
-        FeatureTree proibiospheretree = importer.getFeatureTreeService().find(proIbioTreeUUID);
+        TermTree proibiospheretree = importer.getFeatureTreeService().find(proIbioTreeUUID);
         if (proibiospheretree == null){
-            List<FeatureTree> trees = importer.getFeatureTreeService().list(FeatureTree.class, null, null, null, null);
+            List<TermTree> trees = importer.getFeatureTreeService().list(TermTree.class, null, null, null, null);
             if (trees.size()==1) {
-                FeatureTree ft = trees.get(0);
+                TermTree<Feature> ft = trees.get(0);
                 if (featuresMap==null) {
-                    featuresMap=new HashMap<String, Feature>();
+                    featuresMap=new HashMap<>();
                 }
-                for (Feature feature: ft.getDistinctFeatures()){
+                for (Feature feature: ft.getDistinctTerms()){
                     if(feature!=null) {
                         featuresMap.put(feature.getTitleCache(), feature);
                     }
                 }
             }
-            proibiospheretree = FeatureTree.NewInstance();
+            proibiospheretree = TermTree.NewFeatureInstance();
             proibiospheretree.setUuid(proIbioTreeUUID);
         }
-        //        FeatureNode root = proibiospheretree.getRoot();
-        FeatureNode root2 = proibiospheretree.getRoot();
+
+        TermNode root2 = proibiospheretree.getRoot();
         if (root2 != null){
             int nbChildren = root2.getChildCount()-1;
             while (nbChildren>-1){
@@ -335,7 +335,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         }
 
         for (Feature feature:featuresMap.values()) {
-            root2.addChild(FeatureNode.NewInstance(feature));
+            root2.addChild(feature);
         }
         importer.getFeatureTreeService().saveOrUpdate(proibiospheretree);
 
@@ -349,7 +349,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param refMods: the current reference extracted from the MODS
      */
     /*   @SuppressWarnings("rawtypes")
-    private void extractKey(Node keys, Taxon acceptedTaxon,List<TaxonNameBase> nametosave, Reference<?> refMods) {
+    private void extractKey(Node keys, Taxon acceptedTaxon,List<TaxonName> nametosave, Reference refMods) {
         acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
 
         NodeList children = keys.getChildNodes();
@@ -415,162 +415,9 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         importer.getPolytomousKeyNodeService().saveOrUpdate(polyNodes);
         importer.getPolytomousKeyService().saveOrUpdate(poly);
     }
-     */
-    //    /**
-    //     * @param taxons: the XML Nodegroup
-    //     * @param nametosave: the list of objects to save into the CDM
-    //     * @param acceptedTaxon: the current accepted Taxon
-    //     * @param refMods: the current reference extracted from the MODS
-    //     *
-    //     * @return Taxon object built
-    //     */
-    //    @SuppressWarnings({ "rawtypes", "unchecked" })
-    //    private Taxon getTaxonFromXML(Node taxons, List<TaxonNameBase> nametosave, Reference<?> refMods) {
-    //        //        logger.info("getTaxonFromXML");
-    //        //        logger.info("acceptedTaxon: "+acceptedTaxon);
-    //
-    //        // TaxonNameBase nameToBeFilled = null;
-    //
-    //        currentMyName = new MyName();
-    //        NomenclaturalStatusType statusType = null;
-    //
-    //        try {
-    //            currentMyName = extractScientificName(taxons);
-    //            if (!currentMyName.getStatus().isEmpty()){
-    //                try {
-    //                    statusType = nomStatusString2NomStatus(currentMyName.getStatus());
-    //                } catch (UnknownCdmTypeException e) {
-    //                    addProblematicStatusToFile(currentMyName.getStatus());
-    //                    logger.warn("Problem with status");
-    //                }
-    //            }
-    //
-    //        } catch (TransformerFactoryConfigurationError e1) {
-    //            logger.warn(e1);
-    //        } catch (TransformerException e1) {
-    //            logger.warn(e1);
-    //        }
-    //        /*  INonViralNameParser parser = NonViralNameParserImpl.NewInstance();
-    //
-    //        nameToBeFilled = parser.parseFullName(currentMyName.getName(), nomenclaturalCode, currentMyName.getRank());
-    //        if (nameToBeFilled.hasProblem() &&
-    //                !((nameToBeFilled.getParsingProblems().size()==1) && nameToBeFilled.getParsingProblems().contains(ParserProblem.CheckRank)) ) {
-    //            //            if (nameToBeFilled.hasProblem() && nameToBeFilled.getParsingProblems().contains(ParserProblem.UnparsableNamePart)){
-    //            addProblemNameToFile(currentMyName.getName(),"",nomenclaturalCode,currentMyName.getRank());
-    //            nameToBeFilled=solveNameProblem(currentMyName.getOriginalName(), currentMyName.getName(),parser, currentMyName.getAuthor(), currentMyName.getRank());
-    //        }
-    //
-    //        nameToBeFilled = getTaxonNameBase(nameToBeFilled,nametosave,statusType);
-    //         */
-    //        TaxonNameBase nameToBeFilled = currentMyName.getTaxonNameBase();
-    //        Taxon t = currentMyName.getTaxon();
-    //        //        importer.getNameService().saveOrUpdate(nametosave);
-    //        /*    Taxon t = importer.getTaxonService().findBestMatchingTaxon(nameToBeFilled.getTitleCache());
-    //         */
-    //        boolean statusMatch=false;
-    //        if(t !=null ){
-    //            statusMatch=compareStatus(t, statusType);
-    //        }
-    //        if (t ==null || (t != null && !statusMatch)){
-    //            if(statusType != null) {
-    //                nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
-    //            }
-    //            t= new Taxon(nameToBeFilled,(Reference<?>) nameToBeFilled.getNomenclaturalReference() );//TODO TOFIX reference
-    //            if (t.getSec() == null) {
-    //                t.setSec(refMods);
-    //            }
-    //            if(!configState.getConfig().doKeepOriginalSecundum()) {
-    //                t.setSec(configState.getConfig().getSecundum());
-    //                logger.info("SET SECUNDUM "+configState.getConfig().getSecundum());
-    //            }
-    //            t.addSource(OriginalSourceType.Import,null,null,refMods,null);
-    //            t.addSource(OriginalSourceType.Import, null,null,sourceUrlRef,null);
-    //
-    //
-    //            if (!currentMyName.getIdentifier().isEmpty() && (currentMyName.getIdentifier().length()>2)){
-    //                setLSID(currentMyName.getIdentifier(), t);
-    //            }
-    //
-    //            //            Taxon parentTaxon = currentMyName.getHigherTaxa();
-    //            //            if (parentTaxon == null && !skippQuestion) {
-    //            //                parentTaxon =  askParent(t, classification);
-    //            //            }
-    //            //            if (parentTaxon ==null){
-    //            //                while (parentTaxon == null) {
-    //            //                    System.out.println("parent is null");
-    //            //                    parentTaxon = createParent(t, refMods);
-    //            //                    classification.addParentChild(parentTaxon, t, refMods, null);
-    //            //                }
-    //            //            }else{
-    //            //                classification.addParentChild(parentTaxon, t, refMods, null);
-    //            //            }
-    //        }
-    //        else{
-    //            t = CdmBase.deproxy(t, Taxon.class);
-    //        }
-    //        if (!configState.getConfig().doKeepOriginalSecundum()) {
-    //            t.setSec(configState.getConfig().getSecundum());
-    //            logger.info("SET SECUNDUM "+configState.getConfig().getSecundum());
-    //        }
-    //        return t;
-    //    }
-
+*/
 
 
-
-    //    private Taxon getTaxonFromTaxonNameBase(TaxonNameBase tnb,Reference<?> ref){
-    //        Taxon taxon = null;
-    ////        System.out.println(tnb.getTitleCache());
-    //        Taxon cc= importer.getTaxonService().findBestMatchingTaxon(tnb.getTitleCache());
-    //        if (cc != null){
-    //            if ((cc.getSec() == null || cc.getSec().toString().isEmpty()) || (cc.getSec() != null &&
-    //                    cc.getSec().getTitleCache().equalsIgnoreCase(ref.getTitleCache()))) {
-    //                if(cc.getSec() == null || cc.getSec().toString().isEmpty()){
-    //                    cc.setSec(ref);
-    //                    importer.getTaxonService().saveOrUpdate(cc);
-    //                }
-    //                taxon=cc;
-    //            }
-    //        }
-    //        else{
-    //            //            List<TaxonBase> c = importer.getTaxonService().searchTaxaByName(tnb.getTitleCache(), ref);
-    //            List<TaxonBase> c = importer.getTaxonService().list(TaxonBase.class, 0, 0, null, null);
-    //            for (TaxonBase b : c) {
-    //                try{
-    //                    taxon = (Taxon) b;
-    //                }catch(ClassCastException e){logger.warn("error while casting existing taxonnamebase");}
-    //            }
-    //        }
-    //        if (taxon == null){
-    ////            System.out.println("NEW TAXON HERE "+tnb.toString()+", "+ref.toString());
-    //            taxon = Taxon.NewInstance(tnb, ref); //sec set null
-    //            importer.getTaxonService().save(taxon);
-    //
-    //        }
-    //        taxon = (Taxon) importer.getTaxonService().find(taxon.getUuid());
-    //
-    //        boolean exist = false;
-    //        for (TaxonNode p : classification.getAllNodes()){
-    //            if(p.getTaxon().equals(taxon)) {
-    //                exist =true;
-    //            }
-    //        }
-    //        if (!exist){
-    //            taxon = (Taxon) importer.getTaxonService().find(taxon.getUuid());
-    //            Taxon parentTaxon = currentMyName.getHigherTaxa();
-    //            if (parentTaxon != null) {
-    //                classification.addParentChild(parentTaxon, taxon, ref, null);
-    //            } else {
-    //                System.out.println("HERE???");
-    //                classification.addChildTaxon(taxon, ref, null);
-    //            }
-    //            importer.getClassificationService().saveOrUpdate(classification);
-    //            //                        refreshTransaction();
-    //        }
-    //        taxon = CdmBase.deproxy(taxon, Taxon.class);
-    //        //        System.out.println("TAXON RETOURNE : "+taxon.getTitleCache());
-    //        return taxon;
-    //    }
     /**
      * @param taxons: the XML Nodegroup
      * @param nametosave: the list of objects to save into the CDM
@@ -580,17 +427,18 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @return Taxon object built
      */
     @SuppressWarnings({ "rawtypes", "unused" })
-    private TaxonNameBase getTaxonNameBaseFromXML(Node taxons, List<TaxonNameBase> nametosave, Reference<?> refMods, boolean isSynonym) {
+    private TaxonName getTaxonNameFromXML(Node taxons, List<TaxonName> nametosave, Reference refMods, boolean isSynonym) {
         //        logger.info("getTaxonFromXML");
         //        logger.info("acceptedTaxon: "+acceptedTaxon);
-        logger.info("getTaxonNameBaseFromXML");
-        TaxonNameBase nameToBeFilled = null;
+        logger.info("getTaxonNameFromXML");
+        TaxonName nameToBeFilled = null;
 
         currentMyName=new MyName(isSynonym);
 
         NomenclaturalStatusType statusType = null;
         try {
-            currentMyName = extractScientificName(taxons,refMods);
+               String followingText = null;  //needs to be checked if following text is possible
+            currentMyName = extractScientificName(taxons,refMods, null);
         } catch (TransformerFactoryConfigurationError e1) {
             logger.warn(e1);
         } catch (TransformerException e1) {
@@ -606,67 +454,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             nameToBeFilled=solveNameProblem(currentMyName.getOriginalName(), currentMyName.getName(),parser,currentMyName.getAuthor(), currentMyName.getRank());
         }
 
-        nameToBeFilled = getTaxonNameBase(nameToBeFilled,nametosave,statusType);
+        nameToBeFilled = getTaxonName(nameToBeFilled,nametosave,statusType);
          */
-        nameToBeFilled = currentMyName.getTaxonNameBase();
+        nameToBeFilled = currentMyName.getTaxonName();
         return nameToBeFilled;
 
     }
 
-    //    @SuppressWarnings("rawtypes")
-    //    private TaxonNameBase getTaxonNameBase (TaxonNameBase name, List<TaxonNameBase> nametosave, NomenclaturalStatusType statusType){
-    //        List<TaxonNameBase> names = importer.getNameService().list(TaxonNameBase.class, null, null, null, null);
-    //        for (TaxonNameBase tb : names){
-    //            if (tb.getTitleCache().equalsIgnoreCase(name.getTitleCache())) {
-    //                boolean statusMatch=false;
-    //                if(tb !=null ){
-    //                    statusMatch=compareStatus(tb, statusType);
-    //                }
-    //                if (!statusMatch){
-    //                    if(statusType != null) {
-    //                        name.addStatus(NomenclaturalStatus.NewInstance(statusType));
-    //                    }
-    //                }else
-    //                {
-    //                    logger.info("TaxonNameBase FOUND"+name.getTitleCache());
-    //                    return  CdmBase.deproxy(tb, TaxonNameBase.class);
-    //                }
-    //            }
-    //        }
-    //        //        logger.info("TaxonNameBase NOT FOUND "+name.getTitleCache());
-    //        //        System.out.println("add name "+name);
-    //        nametosave.add(name);
-    //        name = CdmBase.deproxy(name, TaxonNameBase.class);
-    //        return name;
-    //
-    //    }
-
-
-
-    //    /**
-    //     * @param tb
-    //     * @param statusType
-    //     * @return
-    //     */
-    //    private boolean compareStatus(TaxonNameBase tb, NomenclaturalStatusType statusType) {
-    //        boolean statusMatch=false;
-    //        //found one taxon
-    //        Set<NomenclaturalStatus> status = tb.getStatus();
-    //        if (statusType!=null && status.size()>0){ //the statusType is known for both taxon
-    //            for (NomenclaturalStatus st:status){
-    //                NomenclaturalStatusType stype = st.getType();
-    //                if (stype.toString().equalsIgnoreCase(statusType.toString())) {
-    //                    statusMatch=true;
-    //                }
-    //            }
-    //        }
-    //        else{
-    //            if(statusType == null && status.size()==0) {//there is no statusType, we can assume it's the same
-    //                statusMatch=true;
-    //            }
-    //        }
-    //        return statusMatch;
-    //    }
 
     /**
      *
@@ -675,7 +469,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         logger.info("reloadClassification");
         Classification cl = importer.getClassificationService().find(classification.getUuid());
         if (cl != null){
-            classification=cl;
+            classification = cl;
         }else{
             importer.getClassificationService().saveOrUpdate(classification);
             classification = importer.getClassificationService().find(classification.getUuid());
@@ -684,13 +478,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
     //    /**
     //     * Create a Taxon for the current NameBase, based on the current reference
-    //     * @param taxonNameBase
+    //     * @param taxonName
     //     * @param refMods: the current reference extracted from the MODS
     //     * @return Taxon
     //     */
     //    @SuppressWarnings({ "unused", "rawtypes" })
-    //    private Taxon getTaxon(TaxonNameBase taxonNameBase, Reference<?> refMods) {
-    //        Taxon t = new Taxon(taxonNameBase,null );
+    //    private Taxon getTaxon(TaxonName taxonName, Reference refMods) {
+    //        Taxon t = new Taxon(taxonName,null );
     //        if (!configState.getConfig().doKeepOriginalSecundum() || (t.getSec() == null)) {
     //            t.setSec(configState.getConfig().getSecundum());
     //            logger.info("SET SECUNDUM "+configState.getConfig().getSecundum());
@@ -714,7 +508,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
     //        return t;
     //    }
 
-    private void  extractDescriptionWithReference(Node typestatus, Taxon acceptedTaxon, Taxon defaultTaxon, Reference<?> refMods,
+    private void  extractDescriptionWithReference(Node typestatus, Taxon acceptedTaxon, Taxon defaultTaxon, Reference refMods,
             String featureName) {
         //        System.out.println("extractDescriptionWithReference !");
         logger.info("extractDescriptionWithReference");
@@ -735,7 +529,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             }
         }
 
-        Reference<?> currentref =  ReferenceFactory.newGeneric();
+        Reference currentref =  ReferenceFactory.newGeneric();
         if(!r.isEmpty()) {
             currentref.setTitleCache(r, true);
         } else {
@@ -752,12 +546,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param refMods: the current reference extracted from the MODS
      */
     @SuppressWarnings("rawtypes")
-    private void extractDistribution(Node distribution, Taxon acceptedTaxon, Taxon defaultTaxon, List<TaxonNameBase> nametosave, Reference<?> refMods) {
+    private void extractDistribution(Node distribution, Taxon acceptedTaxon, Taxon defaultTaxon, List<TaxonName> nametosave, Reference refMods) {
         logger.info("extractDistribution");
         //        logger.info("acceptedTaxon: "+acceptedTaxon);
         NodeList children = distribution.getChildNodes();
-        Map<Integer,List<MySpecimenOrObservation>> specimenOrObservations = new HashMap<Integer, List<MySpecimenOrObservation>>();
-        Map<Integer,String> descriptionsFulltext = new HashMap<Integer,String>();
+        Map<Integer,List<MySpecimenOrObservation>> specimenOrObservations = new HashMap<>();
+        Map<Integer,String> descriptionsFulltext = new HashMap<>();
 
         for (int i=0;i<children.getLength();i++){
             if (children.item(i).getNodeName().equalsIgnoreCase("tax:p")){
@@ -772,7 +566,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     else if (paragraph.item(j).getNodeName().equalsIgnoreCase("tax:collection_event")){
                         MySpecimenOrObservation specimenOrObservation = new MySpecimenOrObservation();
                         DerivedUnit derivedUnitBase = null;
-                        specimenOrObservation = extractSpecimenOrObservation(paragraph.item(j), derivedUnitBase, SpecimenOrObservationType.DerivedUnit);
+                        specimenOrObservation = extractSpecimenOrObservation(paragraph.item(j), derivedUnitBase, SpecimenOrObservationType.DerivedUnit, null);
                         extractTextFromSpecimenOrObservation(specimenOrObservations, descriptionsFulltext, i, specimenOrObservation);
                     }
                 }
@@ -830,7 +624,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param currentFeature
      * @param k
      */
-    private void handleTextData(Reference<?> refMods, Map<Integer, String> descriptionsFulltext, TaxonDescription td,
+    private void handleTextData(Reference refMods, Map<Integer, String> descriptionsFulltext, TaxonDescription td,
             Feature currentFeature, int k) {
         //logger.info("handleTextData");
         TextData textData = TextData.NewInstance();
@@ -846,7 +640,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param td
      * @param soo
      */
-    private void handleAssociation(Taxon acceptedTaxon, Reference<?> refMods, TaxonDescription td, MySpecimenOrObservation soo) {
+    private void handleAssociation(Taxon acceptedTaxon, Reference refMods, TaxonDescription td, MySpecimenOrObservation soo) {
         logger.info("handleAssociation");
         String descr=soo.getDescr();
         DerivedUnit derivedUnitBase = soo.getDerivedUnitBase();
@@ -854,7 +648,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         sourceHandler.addAndSaveSource(refMods, derivedUnitBase);
 
         TaxonDescription taxonDescription = importer.getTaxonDescription(acceptedTaxon, false, true);
-        
+
         Feature feature=null;
         feature = makeFeature(derivedUnitBase);
         if(!StringUtils.isEmpty(descr)) {
@@ -876,7 +670,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param feature
      * @return
      */
-    private IndividualsAssociation createIndividualAssociation(Reference<?> refMods, DerivedUnit derivedUnitBase,
+    private IndividualsAssociation createIndividualAssociation(Reference refMods, DerivedUnit derivedUnitBase,
             Feature feature) {
         logger.info("createIndividualAssociation");
         IndividualsAssociation indAssociation = IndividualsAssociation.NewInstance();
@@ -918,10 +712,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param paragraph
      */
     @SuppressWarnings("rawtypes")
-    private void extractInLine(List<TaxonNameBase> nametosave, Reference<?> refMods, Map<Integer, String> descriptionsFulltext,
+    private void extractInLine(List<TaxonName> nametosave, Reference refMods, Map<Integer, String> descriptionsFulltext,
             int i, Node paragraph) {
         //logger.info("extractInLine");
-        String inLine=getInlineText(nametosave, refMods, paragraph);
+        String inLine=getInlineTextForName(nametosave, refMods, paragraph);
         if (descriptionsFulltext.get(i) !=null){
             inLine = descriptionsFulltext.get(i)+inLine;
         }
@@ -952,7 +746,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param refMods: the current reference extracted from the MODS
      */
     @SuppressWarnings("rawtypes")
-    private void extractMaterials(Node materials, Taxon acceptedTaxon, Reference<?> refMods,List<TaxonNameBase> nametosave) {
+    private void extractMaterials(Node materials, Taxon acceptedTaxon, Reference refMods,List<TaxonName> nametosave) {
         logger.info("EXTRACTMATERIALS");
         //        logger.info("acceptedTaxon: "+acceptedTaxon);
         NodeList children = materials.getChildNodes();
@@ -967,7 +761,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 events = children.item(i).getChildNodes();
                 for(int k=0;k<events.getLength();k++){
                     if (events.item(k).getNodeName().equalsIgnoreCase("tax:name")){
-                        String inLine= getInlineText(nametosave, refMods, events.item(k));
+                        String inLine= getInlineTextForName(nametosave, refMods, events.item(k));
                         if(!inLine.isEmpty()) {
                             rawAssociation+=inLine;
                         }
@@ -1059,7 +853,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param rawAssociation
      * @param k
      */
-    private void handleDerivedUnitFacadeAndBase(Taxon acceptedTaxon, Reference<?> refMods, Node event,
+    private void handleDerivedUnitFacadeAndBase(Taxon acceptedTaxon, Reference refMods, Node event,
             String rawAssociation) {
         logger.info("handleDerivedUnitFacadeAndBase");
         String descr;
@@ -1070,14 +864,16 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
         sourceHandler.addAndSaveSource(refMods, derivedUnitBase);
 
-        myspecimenOrObservation = extractSpecimenOrObservation(event,derivedUnitBase,SpecimenOrObservationType.DerivedUnit);
+        //TODO this may not always be correct, ask user
+        TaxonName typifiableName = acceptedTaxon != null ?  acceptedTaxon.getName() : null;
+        myspecimenOrObservation = extractSpecimenOrObservation(event,derivedUnitBase,SpecimenOrObservationType.DerivedUnit, typifiableName);
         derivedUnitBase = myspecimenOrObservation.getDerivedUnitBase();
         descr=myspecimenOrObservation.getDescr();
 
         sourceHandler.addAndSaveSource(refMods, derivedUnitBase);
 
         TaxonDescription taxonDescription = importer.getTaxonDescription(acceptedTaxon, false, true);
-        
+
         Feature feature = makeFeature(derivedUnitBase);
         featuresMap.put(feature.getTitleCache(),feature);
         if(!StringUtils.isEmpty(descr)) {
@@ -1094,17 +890,18 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
 
     /**
+     * @param currentName
      * @param materials: the XML node group
      * @param acceptedTaxon: the current accepted Taxon
      * @param refMods: the current reference extracted from the MODS
      */
-    private String extractMaterialsDirect(Node materials, Taxon acceptedTaxon, Reference<?> refMods, String event) {
+    private String extractMaterialsDirect(Node materials, Taxon acceptedTaxon, Reference refMods, String event, TaxonName currentName) {
         logger.info("extractMaterialsDirect");
         //        logger.info("acceptedTaxon: "+acceptedTaxon);
         String descr="";
 
         DerivedUnit derivedUnitBase=null;
-        MySpecimenOrObservation myspecimenOrObservation = extractSpecimenOrObservation(materials,derivedUnitBase, SpecimenOrObservationType.DerivedUnit);
+        MySpecimenOrObservation myspecimenOrObservation = extractSpecimenOrObservation(materials,derivedUnitBase, SpecimenOrObservationType.DerivedUnit, currentName);
         derivedUnitBase = myspecimenOrObservation.getDerivedUnitBase();
 
         sourceHandler.addAndSaveSource(refMods, derivedUnitBase);
@@ -1146,7 +943,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
     @SuppressWarnings({ "rawtypes"})
     private String extractSpecificFeature(Node description, Taxon acceptedTaxon, Taxon defaultTaxon,
-            List<TaxonNameBase> nametosave, Reference<?> refMods, String featureName ) {
+            List<TaxonName> nametosave, Reference refMods, String featureName ) {
         logger.info("extractSpecificFeature "+featureName);
         //        System.out.println("GRUUUUuu");
         NodeList children = description.getChildNodes();
@@ -1191,15 +988,16 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 insideNodes=children.item(i).getChildNodes();
                 blabla= new ArrayList<String>();
                 for (int j=0;j<insideNodes.getLength();j++){
-                    if (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:name")){
-                        String inlinetext = getInlineText(nametosave, refMods, insideNodes.item(j));
+                    Node insideNode = insideNodes.item(j);
+                       if (insideNode.getNodeName().equalsIgnoreCase("tax:name")){
+                        String inlinetext = getInlineTextForName(nametosave, refMods, insideNode);
                         if (!inlinetext.isEmpty()) {
                             blabla.add(inlinetext);
                         }
                     }
-                    if (insideNodes.item(j).getNodeName().equalsIgnoreCase("#text")) {
-                        if(!insideNodes.item(j).getTextContent().trim().isEmpty()){
-                            blabla.add(insideNodes.item(j).getTextContent().trim());
+                    else if (insideNode.getNodeName().equalsIgnoreCase("#text")) {
+                        if(!insideNode.getTextContent().trim().isEmpty()){
+                            blabla.add(insideNode.getTextContent().trim());
                             //                            localdescr += insideNodes.item(j).getTextContent().trim();
                         }
                     }
@@ -1301,10 +1099,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param refMods: the current reference extracted from the MODS
      * @param featureName: the feature name
      */
-    @SuppressWarnings({ "unused", "rawtypes" })
+    @SuppressWarnings({ "unused"})
     private String extractSpecificFeatureNotStructured(Node description, Taxon acceptedTaxon, Taxon defaultTaxon,
-            List<TaxonNameBase> nametosave, Reference<?> refMods, String featureName ) {
-        logger.info("extractSpecificFeatureNotStructured "+featureName);
+            List<TaxonName> nameToSave, Reference refMods, String featureName ) {
+        logger.info("extractSpecificFeatureNotStructured " + featureName);
         NodeList children = description.getChildNodes();
         NodeList insideNodes ;
         List<String> blabla= new ArrayList<String>();
@@ -1318,7 +1116,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 insideNodes=children.item(i).getChildNodes();
                 for (int j=0;j<insideNodes.getLength();j++){
                     if (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:name")){
-                        String inlineText =getInlineText(nametosave, refMods, insideNodes.item(j));
+                        String inlineText =getInlineTextForName(nameToSave, refMods, insideNodes.item(j));
                         if(!inlineText.isEmpty()) {
                             blabla.add(inlineText);
                         }
@@ -1360,36 +1158,46 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @return
      */
     private boolean stringIsEmpty(String blaStr) {
-        if (!StringUtils.isEmpty(blaStr)) {
-            if (!blaStr.equalsIgnoreCase(".")) {
-                if (!blaStr.equalsIgnoreCase(",")) {
-                    if (!blaStr.equalsIgnoreCase(";")) {
-                        return false;
-                    }
-                }
-            }
+        if (blaStr.matches("(\\.|,|;|\\.-)?")){
+               return true;
+        }else{
+               return false;
         }
-        return true;
     }
 
     /**
      * @param nametosave
      * @param refMods
      * @param insideNodes
-     * @param blabla
-     * @param j
      */
-    @SuppressWarnings({ "rawtypes" })
-    private String getInlineText(List<TaxonNameBase> nametosave, Reference<?> refMods, Node insideNode) {
-        //logger.info("getInlineText");
-        TaxonNameBase tnb = getTaxonNameBaseFromXML(insideNode, nametosave,refMods,false);
-        //                        Taxon tax = getTaxonFromTxonNameBase(tnb, refMods);
-        Taxon tax = currentMyName.getTaxon();
-        if(tnb !=null){
-            String linkedTaxon = tnb.toString().split("sec")[0];//TODO NOT IMPLEMENTED IN THE CDM YET
-            return "<cdm:taxon uuid='"+tax.getUuid()+"'>"+linkedTaxon+"</cdm:taxon>";
-        }
-        return "";
+    private String getInlineTextForName(List<TaxonName> nametosave, Reference refMods, Node insideNode) {
+        if (true){
+               NodeList children = insideNode.getChildNodes();
+               String result = "";
+            for (int i=0;i<children.getLength();i++){
+               Node nameChild = children.item(i);
+                if(nameChild.getNodeName().equalsIgnoreCase("#text")){
+                       result += nameChild.getTextContent();
+                }else{
+                       //do nothing
+                }
+            }
+               return result.replace("\n", "").trim();
+        }else{
+               TaxonName tnb = getTaxonNameFromXML(insideNode, nametosave,refMods,false);
+               //                        Taxon tax = getTaxonFromTxonNameBase(tnb, refMods);
+               Taxon tax = currentMyName.getTaxon();
+               if(tnb !=null && tax != null){
+                   String linkedTaxon = tnb.getTitleCache().split("sec")[0];//TODO NOT IMPLEMENTED IN THE CDM YET
+                   return "<cdm:taxon uuid='"+tax.getUuid()+"'>"+linkedTaxon+"</cdm:taxon>";
+               }else if (tnb != null && tax == null){
+                       //TODO
+                       return "<cdm:taxonName uuid='" + tnb.getUuid() +"'>" + tnb.getTitleCache().split("sec")[0]  +"</cdm:taxonName>";
+               }else{
+                       logger.warn("Inline text has no content yet");
+               }
+               return "";
+        }
     }
 
     /**
@@ -1433,7 +1241,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @return a list of description (text)
      */
     @SuppressWarnings({ "unused", "rawtypes" })
-    private List<String> parseParagraph(List<TaxonNameBase> nametosave, Taxon acceptedTaxon, Reference<?> refMods, Node paragraph, Feature feature){
+    private List<String> parseParagraph(List<TaxonName> namesToSave, Taxon acceptedTaxon, Reference refMods, Node paragraph, Feature feature){
         logger.info("parseParagraph "+feature.toString());
         List<String> fullDescription=  new ArrayList<String>();
         //        String localdescr;
@@ -1454,66 +1262,65 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 List<String> blabla= new ArrayList<String>();
                 for (int j=0;j<insideNodes.getLength();j++){
                     boolean nodeKnown = false;
-                    //                    System.out.println("insideNodes.item(j).getNodeName() : "+insideNodes.item(j).getNodeName());
+                    //    System.out.println("insideNodes.item(j).getNodeName() : "+insideNodes.item(j).getNodeName());
                     if (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:name")){
-                        String inlineText = getInlineText(nametosave, refMods, insideNodes.item(j));
+                        String inlineText = getInlineTextForName(namesToSave, refMods, insideNodes.item(j));
                         if (!inlineText.isEmpty()) {
                             blabla.add(inlineText);
                         }
                         nodeKnown=true;
                     }
-                    if (insideNodes.item(j).getNodeName().equalsIgnoreCase("#text")) {
+                    else if (insideNodes.item(j).getNodeName().equalsIgnoreCase("#text")) {
                         if(!insideNodes.item(j).getTextContent().trim().isEmpty()){
                             blabla.add(insideNodes.item(j).getTextContent().trim());
-                            //                            localdescr += insideNodes.item(j).getTextContent().trim();
+                            // localdescr += insideNodes.item(j).getTextContent().trim();
                         }
                         nodeKnown=true;
                     }
-                    if (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:bibref")) {
+                    else if (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:bibref")) {
                         String ref = insideNodes.item(j).getTextContent().trim();
                         if (ref.endsWith(";")  && ((ref.length())>1)) {
                             ref=ref.substring(0, ref.length()-1)+".";
                         }
-                        Reference<?> reference = ReferenceFactory.newGeneric();
+                        Reference reference = ReferenceFactory.newGeneric();
                         reference.setTitleCache(ref, true);
                         blabla.add(reference.getTitleCache());
                         nodeKnown=true;
                     }
-                    if  (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:figure")){
-                        String figure = extractSpecificFeature(insideNodes.item(j),acceptedTaxon,acceptedTaxon, nametosave, refMods, "figure");
+                    else if  (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:figure")){
+                        String figure = extractSpecificFeature(insideNodes.item(j),acceptedTaxon,acceptedTaxon, namesToSave, refMods, "figure");
                         blabla.add(figure);
                     }
-                    if(insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:div") &&
+                    else if(insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:div") &&
                             insideNodes.item(j).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("Other") &&
                             insideNodes.item(j).getAttributes().getNamedItem("otherType").getNodeValue().equalsIgnoreCase("table")){
-                        String table = extractSpecificFeature(insideNodes.item(j),acceptedTaxon,acceptedTaxon, nametosave, refMods, "table");
+                        String table = extractSpecificFeature(insideNodes.item(j),acceptedTaxon,acceptedTaxon, namesToSave, refMods, "table");
                         blabla.add(table);
                     }
-                    if  (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:collection_event")) {
+                    else if  (insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:collection_event")) {
                         //                        logger.warn("SEEMS TO BE COLLECTION EVENT INSIDE A "+feature.toString());
-                        String titlecache  = extractMaterialsDirect(insideNodes.item(j), acceptedTaxon, refMods, "collection");
+                        String titlecache  = extractMaterialsDirect(insideNodes.item(j), acceptedTaxon, refMods, "collection", null);
                         blabla.add(titlecache);
                         collectionEvent=true;
                         collectionEvents.add(insideNodes.item(j));
                         nodeKnown=true;
+                    }else{
+                       logger.warn("node not handled yet: " + insideNodes.item(j).getNodeName());
                     }
-                    //                    if (!nodeKnown && !insideNodes.item(j).getNodeName().equalsIgnoreCase("tax:pb")) {
-                    //                        logger.info("Node not handled yet : "+insideNodes.item(j).getNodeName());
-                    //                    }
 
                 }
-                if (!StringUtils.isEmpty(StringUtils.join(blabla," "))) {
+                if (!StringUtils.isBlank(StringUtils.join(blabla," "))) {
                     fullDescription.add(StringUtils.join(blabla," "));
                 }
             }
             if  (children.item(i).getNodeName().equalsIgnoreCase("tax:figure")){
-                String figure = extractSpecificFeature(children.item(i),acceptedTaxon,acceptedTaxon, nametosave, refMods, "Figure");
+                String figure = extractSpecificFeature(children.item(i),acceptedTaxon,acceptedTaxon, namesToSave, refMods, "Figure");
                 fullDescription.add(figure);
             }
             if(children.item(i).getNodeName().equalsIgnoreCase("tax:div") &&
                     children.item(i).getAttributes().getNamedItem("type").getNodeValue().equalsIgnoreCase("Other") &&
                     children.item(i).getAttributes().getNamedItem("otherType").getNodeValue().equalsIgnoreCase("table")){
-                String table = extractSpecificFeature(children.item(i),acceptedTaxon,acceptedTaxon, nametosave, refMods, "table");
+                String table = extractSpecificFeature(children.item(i),acceptedTaxon,acceptedTaxon, namesToSave, refMods, "table");
                 fullDescription.add(table);
             }
         }
@@ -1541,14 +1348,14 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param feature: the feature to link the data with
      */
     @SuppressWarnings("rawtypes")
-    private void extractFeature(Node description, Taxon acceptedTaxon, Taxon defaultTaxon, List<TaxonNameBase> nametosave, Reference<?> refMods, Feature feature){
+    private void extractFeature(Node description, Taxon acceptedTaxon, Taxon defaultTaxon, List<TaxonName> namesToSave, Reference refMods, Feature feature){
         logger.info("EXTRACT FEATURE "+feature.toString());
         acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
-        List<String> fullDescription= parseParagraph( nametosave, acceptedTaxon, refMods, description,feature);
+        List<String> fullDescription= parseParagraph( namesToSave, acceptedTaxon, refMods, description,feature);
 
         //        System.out.println("Feature : "+feature.toString()+", "+fullDescription.toString());
-        if (!fullDescription.isEmpty() &&!stringIsEmpty(StringUtils.join(fullDescription," ").trim())) {
-            setParticularDescription(StringUtils.join(fullDescription," ").trim(),acceptedTaxon,defaultTaxon, refMods,feature);
+        if (!fullDescription.isEmpty() &&!stringIsEmpty(StringUtils.join(fullDescription,"\n").trim())) {
+            setParticularDescription(StringUtils.join(fullDescription,"\n").trim(),acceptedTaxon,defaultTaxon, refMods,feature);
         }
 
     }
@@ -1562,12 +1369,17 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param currentFeature: the feature name
      * @return
      */
-    private void setParticularDescription(String descr, Taxon acceptedTaxon, Taxon defaultTaxon, Reference<?> refMods, Feature currentFeature) {
-        logger.info("setParticularDescription "+currentFeature.getTitleCache()+", \n blabla : "+descr);
-        //        System.out.println("setParticularDescription "+currentFeature.getTitleCache()+", \n blabla : "+descr);
-        //        logger.info("acceptedTaxon: "+acceptedTaxon);
-        acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
+    private void setParticularDescription(String descr, Taxon acceptedTaxon, Taxon defaultTaxon, Reference refMods, Feature currentFeature) {
+        logger.info("setParticularDescription " + currentFeature.getTitleCache()+", \n blabla : "+descr);
+
+        //remove redundant feature title
+        String featureStr = currentFeature.getTitleCache();
+        if (!descr.isEmpty() && descr.toLowerCase().startsWith(featureStr.toLowerCase())){
+               descr = descr.replaceAll("(?i)" + featureStr + "\\.\\s*", "");
+        }
 
+
+        acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
         featuresMap.put(currentFeature.getTitleCache(),currentFeature);
 
         TextData textData = createTextData(descr, refMods, currentFeature);
@@ -1607,7 +1419,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param currentFeature
      * @return
      */
-    private TextData createTextData(String descr, Reference<?> refMods, Feature currentFeature) {
+    private TextData createTextData(String descr, Reference refMods, Feature currentFeature) {
         //logger.info("createTextData");
         TextData textData = TextData.NewInstance();
         textData.setFeature(currentFeature);
@@ -1627,7 +1439,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param currentFeature: the feature name
      * @return
      */
-    private void setParticularDescription(String descr, Taxon acceptedTaxon, Taxon defaultTaxon,Reference<?> currentRef, Reference<?> refMods, Feature currentFeature) {
+    private void setParticularDescription(String descr, Taxon acceptedTaxon, Taxon defaultTaxon,Reference currentRef, Reference refMods, Feature currentFeature) {
         //        System.out.println("setParticularDescriptionSPecial "+currentFeature);
         //        logger.info("acceptedTaxon: "+acceptedTaxon);
         logger.info("setParticularDescription");
@@ -1674,7 +1486,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param refMods: the current reference extracted from the MODS
      */
     @SuppressWarnings({ "rawtypes" })
-    private void extractSynonyms(Node synonyms, Taxon acceptedTaxon,Reference<?> refMods) {
+    private void extractSynonyms(Node synonymsNode, Taxon acceptedTaxon,Reference refMods, String followingText) {
         logger.info("extractSynonyms");
         //System.out.println("extractSynonyms for: "+acceptedTaxon);
         Taxon ttmp = (Taxon) importer.getTaxonService().find(acceptedTaxon.getUuid());
@@ -1684,14 +1496,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         else{
             acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
         }
-        NodeList children = synonyms.getChildNodes();
-        TaxonNameBase nameToBeFilled = null;
+        NodeList children = synonymsNode.getChildNodes();
         List<MyName> names = new ArrayList<MyName>();
 
-        if(synonyms.getNodeName().equalsIgnoreCase("tax:name")){
-            MyName myName;
+        if(synonymsNode.getNodeName().equalsIgnoreCase("tax:name")){
             try {
-                myName = extractScientificNameSynonym(synonyms,refMods);
+               MyName myName = extractScientificNameSynonym(synonymsNode, refMods, followingText);
                 names.add(myName);
             } catch (TransformerFactoryConfigurationError e) {
                 logger.warn(e);
@@ -1707,23 +1517,20 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 //                String fullContent = children.item(i).getTextContent();
                 for (int j=0; j< tmp.getLength();j++){
                     if(tmp.item(j).getNodeName().equalsIgnoreCase("tax:name")){
-                        MyName myName;
                         try {
-                            myName = extractScientificNameSynonym(tmp.item(j),refMods);
+                               MyName myName = extractScientificNameSynonym(tmp.item(j),refMods, followingText);
                             names.add(myName);
                         } catch (TransformerFactoryConfigurationError e) {
                             logger.warn(e);
                         } catch (TransformerException e) {
                             logger.warn(e);
                         }
-
                     }
                 }
             }
             if(children.item(i).getNodeName().equalsIgnoreCase("tax:name")){
-                MyName myName;
                 try {
-                    myName = extractScientificNameSynonym(children.item(i),refMods);
+                       MyName myName = extractScientificNameSynonym(children.item(i),refMods, followingText);
                     names.add(myName);
                 } catch (TransformerFactoryConfigurationError e) {
                     logger.warn(e);
@@ -1733,16 +1540,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
             }
         }
-        NomenclaturalStatusType statusType = null;
-        //System.out.println("names: "+names);
-        for(MyName name:names){
-            //System.out.println("HANDLE NAME "+name);
-
-            statusType = null;
-
-            nameToBeFilled = name.getTaxonNameBase();
 
+        for(MyName name:names){
+               TaxonName nameToBeFilled = name.getTaxonName();
             Synonym synonym = name.getSyno();
+            addFollowingTextToName(nameToBeFilled, followingText);
+
             /* INonViralNameParser parser = NonViralNameParserImpl.NewInstance();
             nameToBeFilled = parser.parseFullName(name.getName(), nomenclaturalCode, name.getRank());
             if (nameToBeFilled.hasProblem() &&
@@ -1751,17 +1554,16 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 addProblemNameToFile(name.getName(),"",nomenclaturalCode,name.getRank());
                 nameToBeFilled = solveNameProblem(name.getOriginalName(), name.getName(), parser,name.getAuthor(), name.getRank());
             }
-            nameToBeFilled = getTaxonNameBase(nameToBeFilled,nametosave,statusType);
+            nameToBeFilled = getTaxonName(nameToBeFilled,nametosave,statusType);
              */
             if (!name.getIdentifier().isEmpty() && (name.getIdentifier().length()>2)){
                 setLSID(name.getIdentifier(), synonym);
             }
 
             Set<Synonym> synonymsSet= acceptedTaxon.getSynonyms();
-            //            System.out.println(synonym.getName()+" -- "+synonym.getSec());
             boolean synoExist = false;
             for (Synonym syn: synonymsSet){
-                //System.out.println(syn.getName()+" -- "+syn.getSec());
+
                 boolean a =syn.getName().equals(synonym.getName());
                 boolean b = syn.getSec().equals(synonym.getSec());
                 if (a && b) {
@@ -1769,18 +1571,30 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 }
             }
             if (!synonymsSet.contains(synonym) && ! (synoExist)) {
-                //System.out.println("SYNONYM");
                 sourceHandler.addSource(refMods, synonym);
-
-                acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF(),refMods, null);
-
+                acceptedTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
             }
         }
         importer.getTaxonService().saveOrUpdate(acceptedTaxon);
     }
 
 
-    /**
+    private boolean addFollowingTextToName(TaxonName nameToBeFilled, String followingText) {
+       if (nameToBeFilled != null && StringUtils.isNotBlank(followingText)){
+               if (! followingText.matches("\\d\\.?")){
+
+                       if (followingText.startsWith(",")){
+                               followingText = followingText.substring(1).trim();
+                       }
+                       nameToBeFilled.setFullTitleCache(nameToBeFilled.getFullTitleCache()+ "," +followingText , true);
+               }
+               return true;
+       }
+       return false;
+
+       }
+
+       /**
      * @param refgroup: the XML nodes
      * @param nametosave: the list of objects to save into the CDM
      * @param acceptedTaxon: the current acceptedTaxon
@@ -1790,12 +1604,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * handle cases where the bibref are inside <p> and outside
      */
     @SuppressWarnings({ "rawtypes" })
-    private Taxon extractReferences(Node refgroup, List<TaxonNameBase> nametosave, Taxon acceptedTaxon, Reference<?> refMods) {
+    private Taxon extractReferences(Node refgroup, List<TaxonName> nametosave, Taxon acceptedTaxon, Reference refMods) {
         logger.info("extractReferences");
         acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
 
         NodeList children = refgroup.getChildNodes();
-        NonViralName<?> nameToBeFilled = getNonViralNameAccNomenclature();
+        INonViralName nameToBeFilled = getNonViralNameAccNomenclature();
 
         ReferenceBuilder refBuild = new ReferenceBuilder(sourceHandler);
         for (int i=0;i<children.getLength();i++){
@@ -1842,19 +1656,9 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * get the non viral name according to the current nomenclature
      * @return
      */
-    private NonViralName<?> getNonViralNameAccNomenclature() {
-        //logger.info("getNonViralNameAccNomenclature");
-        NonViralName<?> nameToBeFilled = null;
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICNAFP)){
-            nameToBeFilled = BotanicalName.NewInstance(null);
-        }
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)){
-            nameToBeFilled = ZoologicalName.NewInstance(null);
-        }
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICNB)){
-            nameToBeFilled = BacterialName.NewInstance(null);
-        }
-        return nameToBeFilled;
+
+    private INonViralName getNonViralNameAccNomenclature() {
+       return nomenclaturalCode.getNewTaxonNameInstance(null);
     }
 
     /**
@@ -1880,11 +1684,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * handle cases where the bibref are inside <p> and outside
      */
     @SuppressWarnings("rawtypes")
-    private void extractReferenceRawText(NodeList references, NonViralName<?> nameToBeFilled, Reference<?> refMods,
+    private void extractReferenceRawText(NodeList references, INonViralName nameToBeFilled, Reference refMods,
             Taxon acceptedTaxon) {
         logger.info("extractReferenceRawText");
         String refString="";
-        NomenclaturalStatusType statusType = null;
         currentMyName= new MyName(true);
         for (int j=0;j<references.getLength();j++){
             acceptedTaxon=CdmBase.deproxy(acceptedTaxon, Taxon.class);
@@ -1893,12 +1696,9 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             if (references.item(j).getNodeName().equalsIgnoreCase("tax:name")){
 
                 try {
-                    currentMyName = extractScientificName(references.item(j),refMods);
-                    //                    if (myName.getNewName().isEmpty()) {
-                    //                        name=myName.getOriginalName()+"---"+myName.getRank()+"---"+myName.getIdentifier()+"---"+myName.getStatus();
-                    //                    } else {
-                    //                        name=myName.getNewName()+"---"+myName.getRank()+"---"+myName.getIdentifier()+"---"+myName.getStatus();
-                    //                    }
+                       String followingText = null;  //needs to be checked if follText is possible
+                       //TODO create or not create?
+                    currentMyName = extractScientificName(references.item(j), refMods, followingText);
                 } catch (TransformerFactoryConfigurationError e) {
                     logger.warn(e);
                 } catch (TransformerException e) {
@@ -1912,48 +1712,27 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             }
             if(references.item(j).getNodeName().equalsIgnoreCase("#text") && !references.item(j).getTextContent().trim().isEmpty()){
                 //
-                statusType = null;
-                if (!currentMyName.getStatus().isEmpty()){
-                    try {
-                        statusType = nomStatusString2NomStatus(currentMyName.getStatus());
-                    } catch (UnknownCdmTypeException e) {
-                        addProblematicStatusToFile(currentMyName.getStatus());
-                        logger.warn("Problem with status");
-                    }
+               if (!currentMyName.getStatus().isEmpty()){
+                  String nomNovStatus = this.newNameStatus(currentMyName.getStatus());
+                       if (nomNovStatus != null){
+                               nameToBeFilled.setAppendedPhrase(nomNovStatus);
+                       }else{
+                          try {
+                               NomenclaturalStatusType  statusType = nomStatusString2NomStatus(currentMyName.getStatus());
+                            nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
+                           } catch (UnknownCdmTypeException e) {
+                               addProblematicStatusToFile(currentMyName.getStatus());
+                               logger.warn("Problem with status");
+                           }
+                       }
                 }
 
-
-                /*INonViralNameParser parser = NonViralNameParserImpl.NewInstance();*/
                 String fullLineRefName = references.item(j).getTextContent().trim();
                 int nameOrRefOrOther=2;
                 nameOrRefOrOther=askIfNameContained(fullLineRefName);
-                //                System.out.println("NAMEORREFOR?? "+nameOrRefOrOther);
                 if (nameOrRefOrOther==0){
-                    /*TaxonNameBase nameTBF = parser.parseFullName(fullLineRefName, nomenclaturalCode, Rank.UNKNOWN_RANK());
-                    if (nameTBF.hasProblem() &&
-                            !((nameTBF.getParsingProblems().size()==1) && nameTBF.getParsingProblems().contains(ParserProblem.CheckRank)) ) {
-                        addProblemNameToFile(fullLineRefName,"",nomenclaturalCode,Rank.UNKNOWN_RANK());
-                        nameTBF=solveNameProblem(fullLineRefName, fullLineRefName,parser,currentMyName.getAuthor(), currentMyName.getRank());
-                    }
-                    nameTBF = getTaxonNameBase(nameTBF,nametosave,statusType);
-                     */
-                    TaxonNameBase nameTBF = currentMyName.getTaxonNameBase();
-                    Synonym synonym = null;
-                    if (!currentMyName.getStatus().isEmpty()){
-                        try {
-                            statusType = nomStatusString2NomStatus(currentMyName.getStatus());
-                            nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
-                            synonym = Synonym.NewInstance(nameTBF, refMods);
-                        } catch (UnknownCdmTypeException e) {
-                            addProblematicStatusToFile(currentMyName.getStatus());
-                            logger.warn("Problem with status");
-                            synonym = Synonym.NewInstance(nameTBF, refMods);
-                            synonym.setAppendedPhrase(currentMyName.getStatus());
-                        }
-                    }
-                    else{
-                        synonym =  Synonym.NewInstance(nameTBF, refMods);
-                    }
+                    TaxonName nameTBF = currentMyName.getTaxonName();
+                    Synonym synonym = Synonym.NewInstance(nameTBF, refMods);
 
                     Set<Synonym> synonymsSet= acceptedTaxon.getSynonyms();
                     //                    System.out.println(synonym.getName()+" -- "+synonym.getSec());
@@ -1969,39 +1748,24 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     if (!synonymsSet.contains(synonym) && ! (synoExist)) {
                         sourceHandler.addSource(refMods, synonym);
 
-                        acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF(),refMods, null);
+                        acceptedTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
                     }
                 }
 
                 if (nameOrRefOrOther==1){
-                    Reference<?> re = ReferenceFactory.newGeneric();
+                    Reference re = ReferenceFactory.newGeneric();
                     re.setTitleCache(fullLineRefName, true);
 
-                    /* TaxonNameBase nameTBF = parser.parseFullName(currentMyName.getName(), nomenclaturalCode, currentMyName.getRank());
+                    /* TaxonName nameTBF = parser.parseFullName(currentMyName.getName(), nomenclaturalCode, currentMyName.getRank());
                     if (nameTBF.hasProblem() &&
                             !((nameTBF.getParsingProblems().size()==1) && nameTBF.getParsingProblems().contains(ParserProblem.CheckRank)) ) {
                         addProblemNameToFile(currentMyName.getName(),"",nomenclaturalCode,currentMyName.getRank());
                         nameTBF=solveNameProblem(currentMyName.getName(), currentMyName.getName(),parser,currentMyName.getAuthor(), currentMyName.getRank());
                     }
-                    nameTBF = getTaxonNameBase(nameTBF,nametosave,statusType);
+                    nameTBF = getTaxonName(nameTBF,nametosave,statusType);
                      */
-                    TaxonNameBase nameTBF = currentMyName.getTaxonNameBase();
-                    Synonym synonym = null;
-                    if (!currentMyName.getStatus().isEmpty()){
-                        try {
-                            statusType = nomStatusString2NomStatus(currentMyName.getStatus());
-                            nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
-                            synonym = Synonym.NewInstance(nameTBF, refMods);
-                        } catch (UnknownCdmTypeException e) {
-                            addProblematicStatusToFile(currentMyName.getStatus());
-                            logger.warn("Problem with status");
-                            synonym = Synonym.NewInstance(nameTBF, refMods);
-                            synonym.setAppendedPhrase(currentMyName.getStatus());
-                        }
-                    }
-                    else{
-                        synonym =  Synonym.NewInstance(nameTBF, refMods);
-                    }
+                    TaxonName nameTBF = currentMyName.getTaxonName();
+                    Synonym synonym = Synonym.NewInstance(nameTBF, re);
 
                     Set<Synonym> synonymsSet= acceptedTaxon.getSynonyms();
                     //                    System.out.println(synonym.getName()+" -- "+synonym.getSec());
@@ -2017,7 +1781,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     if (!synonymsSet.contains(synonym) && ! (synoExist)) {
                         sourceHandler.addSource(refMods, synonym);
 
-                        acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF(),re, null);
+                        acceptedTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
                     }
 
                 }
@@ -2031,7 +1795,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             if(!currentMyName.getName().isEmpty()){
                 //logger.info("acceptedTaxon and name: *"+acceptedTaxon.getTitleCache()+"*, *"+currentMyName.getName()+"*");
                 if (acceptedTaxon.getTitleCache().split("sec")[0].trim().equalsIgnoreCase(currentMyName.getName().trim())){
-                    Reference<?> refS = ReferenceFactory.newGeneric();
+                    Reference refS = ReferenceFactory.newGeneric();
                     refS.setTitleCache(refString, true);
                     //                            TaxonDescription td =importer.getTaxonDescription(acceptedTaxon, false, true);
                     //                            acceptedTaxon.addDescription(td);
@@ -2051,33 +1815,26 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     }
 
                     acceptedTaxon.getName().setNomenclaturalReference(refS);
-                }
-                else{
-                    /* INonViralNameParser parser = NonViralNameParserImpl.NewInstance();
-                    TaxonNameBase nameTBF = parser.parseFullName(currentMyName.getName(), nomenclaturalCode, currentMyName.getRank());
-                    if (nameTBF.hasProblem() &&
-                            !((nameTBF.getParsingProblems().size()==1) && nameTBF.getParsingProblems().contains(ParserProblem.CheckRank)) ) {
-                        //            if (nameToBeFilled.hasProblem() && nameToBeFilled.getParsingProblems().contains(ParserProblem.UnparsableNamePart)){
-                        addProblemNameToFile(currentMyName.getName(),"",nomenclaturalCode,currentMyName.getRank());
-                        nameTBF=solveNameProblem(currentMyName.getOriginalName(), currentMyName.getName(),parser,currentMyName.getAuthor(), currentMyName.getRank());
-                    }
-                    nameTBF = getTaxonNameBase(nameTBF,nametosave,statusType);
-                     */
-                    TaxonNameBase nameTBF = currentMyName.getTaxonNameBase();
+                }else{
+                    TaxonName nameTBF = currentMyName.getTaxonName();
                     Synonym synonym = null;
-                    if (!currentMyName.getStatus().isEmpty()){
-                        try {
-                            statusType = nomStatusString2NomStatus(currentMyName.getStatus());
-                            nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
-                            synonym = Synonym.NewInstance(nameTBF, refMods);
-                        } catch (UnknownCdmTypeException e) {
-                            addProblematicStatusToFile(currentMyName.getStatus());
-                            logger.warn("Problem with status");
-                            synonym = Synonym.NewInstance(nameTBF, refMods);
-                            synonym.setAppendedPhrase(currentMyName.getStatus());
-                        }
-                    }
-                    else{
+                    if (! currentMyName.getStatus().isEmpty()){
+                       String nomNovStatus = this.newNameStatus(currentMyName.getStatus());
+                       if (nomNovStatus != null){
+                               nameToBeFilled.setAppendedPhrase(nomNovStatus);
+                       }else{
+                               try {
+                                   NomenclaturalStatusType statusType = nomStatusString2NomStatus(currentMyName.getStatus());
+                                   nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
+                                   synonym = Synonym.NewInstance(nameTBF, refMods);
+                               } catch (UnknownCdmTypeException e) {
+                                   addProblematicStatusToFile(currentMyName.getStatus());
+                                   logger.warn("Problem with status");
+                                   synonym = Synonym.NewInstance(nameTBF, refMods);
+                                   synonym.setAppendedPhrase(currentMyName.getStatus());
+                               }
+                       }
+                    }else{
                         synonym =  Synonym.NewInstance(nameTBF, refMods);
                     }
 
@@ -2100,7 +1857,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     if (!synonymsSet.contains(synonym) && ! (synoExist)) {
                         sourceHandler.addSource(refMods, synonym);
 
-                        acceptedTaxon.addSynonym(synonym, SynonymRelationshipType.SYNONYM_OF(),refMods, null);
+                        acceptedTaxon.addSynonym(synonym, SynonymType.SYNONYM_OF());
                     }
                 }
             }
@@ -2134,8 +1891,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         //logger.info("search reference for LSID");
         //  if ((id.indexOf("lsid")<0) || !lsidok){
         //ADD ORIGINAL SOURCE ID EVEN IF LSID
-        Reference<?> re = null;
-        Pager<Reference> references = importer.getReferenceService().findByTitle(Reference.class, source, MatchMode.EXACT, null, 1, null, null, null);
+        Reference re = null;
+        Pager<Reference> references = importer.getReferenceService().findByTitleWithRestrictions(Reference.class, source, MatchMode.EXACT, null, 1, null, null, null);
         if( references !=null && references.getCount()>0){
             re=references.getRecords().get(0);
         }
@@ -2176,10 +1933,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param original : the name from the OCR document
      * @param name : the tagged version
      * @param parser
-     * @return the corrected TaxonNameBase
+     * @return the corrected TaxonName
      */
     /*   @SuppressWarnings({ "unchecked", "rawtypes" })
-    private TaxonNameBase<?,?> solveNameProblem(String original, String name, INonViralNameParser parser, String author, Rank rank) {
+    private TaxonName solveNameProblem(String original, String name, INonViralNameParser parser, String author, Rank rank) {
         Map<String,String> ato = namesMap.get(original);
         if (ato == null) {
             ato = namesMap.get(original+" "+author);
@@ -2192,8 +1949,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         if (ato != null && rank.equals(Rank.UNKNOWN_RANK())){
             rank = getRank(ato);
         }
-        //        TaxonNameBase<?,?> nameTBF = parser.parseFullName(name, nomenclaturalCode, rank);
-        TaxonNameBase<?,?> nameTBF = parser.parseSimpleName(name, nomenclaturalCode, rank);
+        //        TaxonName nameTBF = parser.parseFullName(name, nomenclaturalCode, rank);
+        TaxonName nameTBF = parser.parseSimpleName(name, nomenclaturalCode, rank);
         //                logger.info("RANK: "+rank);
         int retry=0;
         List<ParserProblem> problems = nameTBF.getParsingProblems();
@@ -2207,13 +1964,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 fullname =  getFullReference(name,nameTBF.getParsingProblems());
             }
             if (nomenclaturalCode.equals(NomenclaturalCode.ICNAFP)){
-                nameTBF = BotanicalName.NewInstance(null);
+                nameTBF = TaxonNameFactory.NewBotanicalInstance(null);
             }
             if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)){
-                nameTBF = ZoologicalName.NewInstance(null);
+                nameTBF = TaxonNameFactory.NewZoologicalInstance(null);
             }
-            if (nomenclaturalCode.equals(NomenclaturalCode.ICNB)){
-                nameTBF= BacterialName.NewInstance(null);
+            if (nomenclaturalCode.equals(NomenclaturalCode.ICNP)){
+                nameTBF= TaxonNameFactory.NewBacterialInstance(null);
             }
             parser.parseReferencedName(nameTBF, fullname, rank, false);
             retry++;
@@ -2244,7 +2001,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)) {
                         ((ZoologicalName) nameTBF).setAuthorshipCache(currentMyName.getAuthor());
                     }
-                    if (nomenclaturalCode.equals(NomenclaturalCode.ICNB)) {
+                    if (nomenclaturalCode.equals(NomenclaturalCode.ICNP)) {
                         ((BacterialName) nameTBF).setAuthorshipCache(currentMyName.getAuthor());
                     }
                 }
@@ -2265,63 +2022,91 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @return
      */
     @SuppressWarnings({ "rawtypes" })
-    private Taxon extractNomenclature(Node nomenclatureNode,  List<TaxonNameBase> nametosave, Reference<?> refMods) throws ClassCastException{
+    private Taxon extractNomenclature(Node nomenclatureNode,  List<TaxonName> nametosave, Reference refMods) throws ClassCastException{
         refMods=CdmBase.deproxy(refMods, Reference.class);
 
         logger.info("extractNomenclature");
         NodeList children = nomenclatureNode.getChildNodes();
         String freetext="";
-        NonViralName<?> nameToBeFilled = null;
         Taxon acceptedTaxon = null;
         //   INonViralNameParser parser = NonViralNameParserImpl.NewInstance();
 
         //        String fullContent = nomenclatureNode.getTextContent();
 
         NomenclaturalStatusType statusType = null;
+        String newNameStatus = null;
+        //TODO
         for (int i=0;i<children.getLength();i++){
             if(children.item(i).getNodeName().equalsIgnoreCase("tax:status")){
                 String status = children.item(i).getTextContent().trim();
+
                 if (!status.isEmpty()){
-                    try {
-                        statusType = nomStatusString2NomStatus(status);
-                    } catch (UnknownCdmTypeException e) {
-                        addProblematicStatusToFile(status);
-                        logger.warn("Problem with status");
+                       if (newNameStatus(status) != null){
+                               newNameStatus = newNameStatus(status);
+                    }else{
+                           try {
+                               statusType = nomStatusString2NomStatus(status);
+                           } catch (UnknownCdmTypeException e) {
+       //                      nomNovStatus;
+                               addProblematicStatusToFile(status);
+                               logger.warn("Problem with status: " + status);
+                           }
                     }
                 }
             }
         }
 
         boolean containsSynonyms=false;
-        for (int i=0;i<children.getLength();i++){
-
-            if (children.item(i).getNodeName().equalsIgnoreCase("#text")) {
-                freetext=children.item(i).getTextContent();
-            }
-            if (children.item(i).getNodeName().equalsIgnoreCase("tax:collection_event")) {
+        boolean wasSynonym = false;
+        usedFollowingTextPrefix = null;  //reset
+
+        for (int i=0; i<children.getLength(); i++){
+               Node childNode = children.item(i);
+               String childName = childNode.getNodeName();
+
+
+               //following text
+               followingText = null;
+               if ( i + 1 < children.getLength()){
+               Node followingTextNode = children.item(i +1);
+               if (followingTextNode.getNodeName().equals("#text") && !followingTextNode.getTextContent().matches("\\s*") ){
+                       followingText = followingTextNode.getTextContent();
+               }
+               }
+
+               //traverse nodes
+            if (childName.equalsIgnoreCase("#text")) {
+                freetext = childNode.getTextContent().trim();
+                if (usedFollowingTextPrefix != null && freetext.startsWith(usedFollowingTextPrefix)){
+                       freetext = freetext.substring(usedFollowingTextPrefix.length());
+                }
+                usedFollowingTextPrefix = null;  //reset
+            }else if (childName.equalsIgnoreCase("tax:collection_event")) {
                 //                System.out.println("COLLECTION EVENT INSIDE NOMENCLATURE");
-                extractMaterialsDirect(children.item(i), acceptedTaxon, refMods, "collection");
-            }
-            if(children.item(i).getNodeName().equalsIgnoreCase("tax:name")){
+                extractMaterialsDirect(childNode, acceptedTaxon, refMods, "collection", currentMyName.getTaxonName());
+            }else if(childName.equalsIgnoreCase("tax:name")){
+                INonViralName nameToBeFilled;
                 //System.out.println("HANDLE FIRST NAME OF THE LIST");
                 if(!containsSynonyms){
-                    //System.out.println("I : "+i);
+                       wasSynonym = false;
+
+                       //System.out.println("I : "+i);
                     currentMyName = new MyName(false);
                     try {
-                        currentMyName = extractScientificName(children.item(i),refMods);
+                        currentMyName = extractScientificName(childNode, refMods, followingText);
                         treatmentMainName = currentMyName.getNewName();
                         originalTreatmentName = currentMyName.getOriginalName();
 
                     } catch (TransformerFactoryConfigurationError e1) {
-                        logger.warn(e1);
+                        throw new RuntimeException(e1);
                     } catch (TransformerException e1) {
-                        logger.warn(e1);
+                       throw new RuntimeException(e1);
                     }
 
-                    if (currentMyName.getRank().equals(Rank.UNKNOWN_RANK()) || currentMyName.getRank().isLower(configState.getConfig().getMaxRank()) || currentMyName.getRank().equals(configState.getConfig().getMaxRank())){
+                    if (currentMyName.getRank().equals(Rank.UNKNOWN_RANK()) || currentMyName.getRank().isLower(state2.getConfig().getMaxRank()) || currentMyName.getRank().equals(state2.getConfig().getMaxRank())){
                         maxRankRespected=true;
 
-                        nameToBeFilled=currentMyName.getTaxonNameBase();
+                        nameToBeFilled=currentMyName.getTaxonName();
 
                         //   acceptedTaxon = importer.getTaxonService().findBestMatchingTaxon(treatmentMainName);
                         acceptedTaxon=currentMyName.getTaxon();
@@ -2336,8 +2121,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                         }
                         if (acceptedTaxon ==null || (acceptedTaxon != null && !statusMatch)){
 
-                            nameToBeFilled=currentMyName.getTaxonNameBase();
-                            if (nameToBeFilled!=null){
+                            nameToBeFilled=currentMyName.getTaxonName();
+                            if (nameToBeFilled != null){
                                 if (!originalTreatmentName.isEmpty()) {
                                     TaxonNameDescription td = TaxonNameDescription.NewInstance();
                                     td.setTitleCache(originalTreatmentName, true);
@@ -2347,21 +2132,24 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                                 if(statusType != null) {
                                     nameToBeFilled.addStatus(NomenclaturalStatus.NewInstance(statusType));
                                 }
-                                sourceHandler.addSource(refMods, nameToBeFilled);
+                                if(newNameStatus != null){
+                                       nameToBeFilled.setAppendedPhrase(newNameStatus);
+                                }
+                                sourceHandler.addSource(refMods, TaxonName.castAndDeproxy(nameToBeFilled));
 
                                 if (nameToBeFilled.getNomenclaturalReference() == null) {
-                                    acceptedTaxon= new Taxon(nameToBeFilled,refMods);
+                                    acceptedTaxon= Taxon.NewInstance(nameToBeFilled,refMods);
                                     //System.out.println("NEW ACCEPTED HERE "+nameToBeFilled);
                                 }
                                 else {
-                                    acceptedTaxon= new Taxon(nameToBeFilled,(Reference<?>) nameToBeFilled.getNomenclaturalReference() );//TODO TOFIX reference
+                                    acceptedTaxon= Taxon.NewInstance(nameToBeFilled,nameToBeFilled.getNomenclaturalReference() );//TODO TOFIX reference
                                     //System.out.println("NEW ACCEPTED HERE2 "+nameToBeFilled);
                                 }
 
                                 sourceHandler.addSource(refMods, acceptedTaxon);
 
-                                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                                    acceptedTaxon.setSec(configState.getConfig().getSecundum());
+                                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                                    acceptedTaxon.setSec(state2.getConfig().getSecundum());
                                     //logger.info("SET SECUNDUM "+configState.getConfig().getSecundum());
                                     //System.out.println("SET SECUNDUM "+configState.getConfig().getSecundum());
                                 }
@@ -2384,20 +2172,21 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                                     sourcelinked=true;
                                 }
                             }
-                            if (!configState.getConfig().doKeepOriginalSecundum()) {
-                                acceptedTaxon.setSec(configState.getConfig().getSecundum());
+                            if (!state2.getConfig().doKeepOriginalSecundum()) {
+                                acceptedTaxon.setSec(state2.getConfig().getSecundum());
                                 //logger.info("SET SECUNDUM "+configState.getConfig().getSecundum());
                                 //System.out.println("SET SECUNDUM "+configState.getConfig().getSecundum());
                             }
                             importer.getTaxonService().saveOrUpdate(acceptedTaxon);
-                            acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
+
                             if (!sourcelinked){
                                 sourceHandler.addSource(refMods, acceptedTaxon);
                             }
-                            if (!sourcelinked || !configState.getConfig().doKeepOriginalSecundum()){
+                            if (!sourcelinked || !state2.getConfig().doKeepOriginalSecundum()){
 
                                 if (!currentMyName.getIdentifier().isEmpty() && (currentMyName.getIdentifier().length()>2)){
-                                    setLSID(currentMyName.getIdentifier(), acceptedTaxon);
+                                    //FIXME are these identifiers really related to taxa, not names? Exiting LSIDs come from Zoobank, urn:lsid:biosci.ohio-state.edu:osuc_concepts:134826 (Ants)
+                                       setLSID(currentMyName.getIdentifier(), acceptedTaxon);
                                 }
                                 importer.getTaxonService().saveOrUpdate(acceptedTaxon);
                             }
@@ -2405,33 +2194,56 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     }else{
                         maxRankRespected=false;
                     }
-                    containsSynonyms=true;
+                    containsSynonyms=true;  //all folowing names are handled as synonyms
                 }else{
-                    //System.out.println("YOUHOUUU "+i);
                     try{
-                        extractSynonyms(children.item(i), acceptedTaxon, refMods);
+                        extractSynonyms(childNode, acceptedTaxon, refMods, followingText);
+                        wasSynonym = true;
+
                     }catch(NullPointerException e){
-                        logger.warn("nullpointerexception, the accepted taxon might be null");
+                        logger.warn("null pointer exception, the accepted taxon might be null");
                     }
                 }
                 containsSynonyms=true;
-            }
-            if (children.item(i).getNodeName().equalsIgnoreCase("tax:ref_group") && maxRankRespected){
+            }else if (childName.equalsIgnoreCase("tax:ref_group") && maxRankRespected){
                 reloadClassification();
                 //extract the References within the document
-                extractReferences(children.item(i),nametosave,acceptedTaxon,refMods);
+                extractReferences(childNode,nametosave,acceptedTaxon,refMods);
+            }else if (childName.equalsIgnoreCase("tax:bibref")){
+               logger.warn(childName + " still preliminary");
+
+               TaxonName currentName = currentMyName == null ? null : currentMyName.getTaxonName();
+               boolean handled = addFollowingTextToName (currentName, childNode.getTextContent() );
+               if (! handled){
+                       setParticularDescription(freetext.trim(), acceptedTaxon,acceptedTaxon, refMods, getNotMarkedUpFeatureObject());
+               }
+            }else{
+               logger.warn(childName + " not yet handled");
             }
-            if(!stringIsEmpty(freetext.trim())) {
-                setParticularDescription(freetext.trim(), acceptedTaxon,acceptedTaxon, refMods, getNotMarkedUpFeatureObject());
+            if(!stringIsEmpty(freetext.trim())) {;
+                if (! freetext.matches("\\d\\.?")){
+                    TaxonName currentName = currentMyName == null ? null : currentMyName.getTaxonName();
+                       boolean handled = false;
+                       if (currentName != null && !wasSynonym){
+                               handled = addFollowingTextToName (currentName, childNode.getTextContent() );
+                       }
+                       if (! handled){
+                               setParticularDescription(freetext.trim(), acceptedTaxon,acceptedTaxon, refMods, getNotMarkedUpFeatureObject());
+                       }
+                }
+
+                 freetext = "";
             }
 
         }
-        //        importer.getClassificationService().saveOrUpdate(classification);
+        //importer.getClassificationService().saveOrUpdate(classification);
         return acceptedTaxon;
     }
 
 
-    /**
+
+
+       /**
      * @return
      */
 
@@ -2461,7 +2273,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param ref: the current reference extracted from the MODS
      * @return the parent for the current accepted taxon
      */
-    /*  private Taxon createParent(Taxon acceptedTaxon, Reference<?> ref) {
+    /*  private Taxon createParent(Taxon acceptedTaxon, Reference ref) {
         acceptedTaxon = CdmBase.deproxy(acceptedTaxon, Taxon.class);
 
         List<Rank> rankList = new ArrayList<Rank>();
@@ -2483,15 +2295,15 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     s = askSetParent(s);
                     r = askRank(s,rankListStr);
 
-                    NonViralName<?> nameToBeFilled = null;
+                    TaxonName nameToBeFilled = null;
                     if (nomenclaturalCode.equals(NomenclaturalCode.ICNAFP)){
-                        nameToBeFilled = BotanicalName.NewInstance(null);
+                        nameToBeFilled = TaxonNameFactory.NewBotanicalInstance(null);
                     }
                     if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)){
-                        nameToBeFilled = ZoologicalName.NewInstance(null);
+                        nameToBeFilled = TaxonNameFactory.NewZoologicalInstance(null);
                     }
-                    if (nomenclaturalCode.equals(NomenclaturalCode.ICNB)){
-                        nameToBeFilled = BacterialName.NewInstance(null);
+                    if (nomenclaturalCode.equals(NomenclaturalCode.ICNP)){
+                        nameToBeFilled = TaxonNameFactory.NewBacterialInstance(null);
                     }
                     nameToBeFilled.setTitleCache(s, true);
                     nameToBeFilled.setRank(getRank(r), true);
@@ -2522,7 +2334,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
 
 
-    private MyName  extractScientificNameSynonym(Node name, Reference<?> refMods) throws TransformerFactoryConfigurationError, TransformerException {
+    private MyName  extractScientificNameSynonym(Node name, Reference refMods, String followingText) throws TransformerFactoryConfigurationError, TransformerException {
         //System.out.println("extractScientificNameSynonym");
         logger.info("extractScientificNameSynonym");
         String[] rankListToPrint_tmp ={"dwc:genus","dwc:specificepithet","dwc:species","dwc:subspecies", "dwc:infraspecificepithet","dwc:scientificnameauthorship"};
@@ -2537,7 +2349,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         String fullName = "";
         String newName="";
         String identifier="";
-        HashMap<String, String> atomisedMap = new HashMap<String, String>();
+        HashMap<String, String> atomisedMap = new HashMap<>();
         List<String> atomisedName= new ArrayList<String>();
 
         String rankStr = "";
@@ -2621,24 +2433,24 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
         boolean parseNameManually=false;
         INonViralNameParser<?> parser = NonViralNameParserImpl.NewInstance();
-        TaxonNameBase<?,?>  nameToBeFilledTest ;
+        TaxonName nameToBeFilledTest ;
 
         //if selected the atomised version
         if(newName==atomisedNameStr){
-            nameToBeFilledTest = parser.parseFullName(atomisedNameStr, nomenclaturalCode, rank);
+            nameToBeFilledTest = parseWithExtension(parser, atomisedNameStr, rank, followingText, atomisedMap);
             if (nameToBeFilledTest.hasProblem()){
                 addProblemNameToFile("ato",atomisedNameStr,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
-                nameToBeFilledTest = parser.parseFullName(fullName, nomenclaturalCode,rank);
+                nameToBeFilledTest = (TaxonName)parser.parseFullName(fullName, nomenclaturalCode, rank);
                 if (nameToBeFilledTest.hasProblem()){
                     addProblemNameToFile("full",fullName,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
                     parseNameManually=true;
                 }
             }
         }else{
-            nameToBeFilledTest = parser.parseFullName(fullName, nomenclaturalCode, rank);
+            nameToBeFilledTest = parseWithExtension(parser, atomisedNameStr, rank, followingText, atomisedMap);
             if (nameToBeFilledTest.hasProblem()){
-                addProblemNameToFile("fullversion",fullName,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
-                nameToBeFilledTest = parser.parseFullName(fullName, nomenclaturalCode,rank);
+                addProblemNameToFile("fullversion",fullName, nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
+                nameToBeFilledTest = (TaxonName)parser.parseFullName(fullName, nomenclaturalCode,rank);
                 parseNameManually=true;
                 if(!originalName.equalsIgnoreCase(atomisedNameStr)) {
                     addNameDifferenceToFile(originalName,atomisedNameStr);
@@ -2648,9 +2460,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
         if(parseNameManually){
             //System.out.println("DO IT MANUALLY");
-            createSynonym(rank, newName, atomisedMap, myname);
-        }
-        else{
+               if (this.state2.getConfig().isUseOldUnparsedSynonymExtraction()){
+                createUnparsedSynonym(rank, newName, atomisedMap, myname);
+               }else{
+                       createUnparsedSynonymNew(rank, newName, atomisedMap, myname, refMods);;
+               }
+        } else{
             //System.out.println("AUTOMATIC!");
             //            createAtomisedTaxonString(newName, atomisedMap, myname);
             myname.setParsedName(nameToBeFilledTest);
@@ -2659,88 +2474,79 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         //System.out.println("RETURN SYNONYM "+myname.getSyno().toString());
         return myname;
     }
-    /**
+
+
+       /**
      * @param name
      * @throws TransformerFactoryConfigurationError
      * @throws TransformerException
      * @return a list of possible names
      */
-    @SuppressWarnings({ "null", "rawtypes" })
-    private MyName extractScientificName(Node name, Reference<?> refMods) throws TransformerFactoryConfigurationError, TransformerException {
+    @SuppressWarnings({"rawtypes" })
+    private MyName extractScientificName(Node name, Reference refMods, String followingText) throws TransformerFactoryConfigurationError, TransformerException {
         logger.info("extractScientificName");
 
-        String[] rankListToPrint_tmp ={"dwc:genus","dwc:specificepithet","dwc:species","dwc:subspecies", "dwc:infraspecificepithet","dwc:scientificnameauthorship"};
-        List<String> rankListToPrint = new ArrayList<String>();
-        for (String r : rankListToPrint_tmp) {
-            rankListToPrint.add(r.toLowerCase());
-        }
+        String[] rankListToPrintLowerCase_tmp ={"dwc:genus","dwc:specificepithet","dwc:species","dwc:subspecies", "dwc:infraspecificepithet","dwc:scientificnameauthorship"};
+        List<String> rankListToPrint = Arrays.asList(rankListToPrintLowerCase_tmp);
 
         Rank rank = Rank.UNKNOWN_RANK();
         NodeList children = name.getChildNodes();
-        String originalName="";
+        String originalName = "";
         String fullName = "";
-        String newName="";
-        String identifier="";
-        HashMap<String, String> atomisedMap = new HashMap<String, String>();
-        List<String> atomisedName= new ArrayList<String>();
-
-        String rankStr = "";
-        Rank tmpRank ;
+        String newName = "";
+        String identifier = "";
+        HashMap<String, String> atomisedMap = new HashMap<>();
+        List<String> atomisedNameList= new ArrayList<>();
 
         String status= extractStatus(children);
 
         for (int i=0;i<children.getLength();i++){
-            if(children.item(i).getNodeName().equalsIgnoreCase("tax:xmldata")){
-                NodeList atom = children.item(i).getChildNodes();
-                for (int k=0;k<atom.getLength();k++){
-                    identifier = extractIdentifier(identifier, atom.item(k));
-                    tmpRank = null;
-                    rankStr = atom.item(k).getNodeName().toLowerCase();
-                    //                    logger.info("RANKSTR:*"+rankStr+"*");
+               Node nameChild = children.item(i);
+            if(nameChild.getNodeName().equalsIgnoreCase("tax:xmldata")){
+                NodeList xmlDataChildren = nameChild.getChildNodes();
+                for (int k=0;k<xmlDataChildren.getLength();k++){
+                       Node xmlDataChild = xmlDataChildren.item(k);
+                    identifier = extractIdentifier(identifier, xmlDataChild);
+                    String rankStr = xmlDataChild.getNodeName().toLowerCase();
                     if (rankStr.equalsIgnoreCase("dwc:taxonRank")) {
-                        rankStr=atom.item(k).getTextContent().trim();
-                        tmpRank = getRank(rankStr);
+                        rankStr=xmlDataChild.getTextContent().trim();
+                        Rank tmpRank = getRank(rankStr);
+                        if (tmpRank != null){
+                            rank=tmpRank;
+                        }
                     }
                     //                    if ((tmpRank != null) && (tmpRank.isLower(rank) || rank.equals(Rank.UNKNOWN_RANK()))) {
-                    if (tmpRank != null){
-                        rank=tmpRank;
-                    }
-                    atomisedMap.put(rankStr.toLowerCase(),atom.item(k).getTextContent().trim());
+
+                    atomisedMap.put(rankStr.toLowerCase(),xmlDataChild.getTextContent().trim());
                 }
-                addAtomisedNamesToMap(rankListToPrint, rank, atomisedName, atom);
+                addAtomisedNamesToMap(rankListToPrint, rank, atomisedNameList, xmlDataChildren);
             }
-            if(children.item(i).getNodeName().equalsIgnoreCase("#text") && !StringUtils.isBlank(children.item(i).getTextContent())){
+            else if(nameChild.getNodeName().equalsIgnoreCase("#text") && ! nameChild.getTextContent().matches("\\s*")){
                 //                logger.info("name non atomised: "+children.item(i).getTextContent());
-                fullName = children.item(i).getTextContent().trim();
+                fullName = nameChild.getTextContent().trim();
                 //                logger.info("fullname: "+fullName);
             }
         }
         originalName=fullName;
-        fullName = cleanName(fullName, atomisedName);
+        fullName = cleanName(fullName, atomisedNameList);
         namesMap.put(fullName,atomisedMap);
 
-        String atomisedNameStr = getAtomisedNameStr(atomisedName);
+        String atomisedNameStr = getAtomisedNameStr(atomisedNameList);
 
         if (fullName != null){
-            //            System.out.println("fullname: "+fullName);
-            //            System.out.println("atomised: "+atomisedNameStr);
             if (!fullName.equalsIgnoreCase(atomisedNameStr)) {
-                //System.out.println("atomisedNameStr vs. fullName:"+atomisedNameStr+"--"+fullName);
                 if (skippQuestion){
-                    //                    String defaultN = "";
                     if (atomisedNameStr.length()>fullName.length()) {
-                        newName=atomisedNameStr;
+                        newName = atomisedNameStr;
                     } else {
                         if (fullName.length()>atomisedNameStr.length() && (rank.isLower(Rank.SPECIES()) && fullName.length()>2 && !fullName.substring(0, 1).equals("."))) {
-                            //System.out.println("là");
-                            newName=askWhichScientificName(fullName,atomisedNameStr,classification.getTitleCache(),name);
+                            newName = askWhichScientificName(fullName, atomisedNameStr, classification.getTitleCache(), name);
                         } else {
-                            //System.out.println("ici");
-                            newName=fullName;
+                            newName = fullName;
                         }
                     }
                 } else {
-                    newName=askWhichScientificName(fullName,atomisedNameStr,classification.getTitleCache(),name);
+                    newName=askWhichScientificName(fullName, atomisedNameStr, classification.getTitleCache(), name);
                 }
             } else {
                 newName=fullName;
@@ -2769,24 +2575,24 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
         boolean parseNameManually=false;
         INonViralNameParser parser = NonViralNameParserImpl.NewInstance();
-        TaxonNameBase  nameToBeFilledTest = null;
+        TaxonName  nameToBeFilledTest = null;
 
         //if selected the atomised version
         if(newName==atomisedNameStr){
-            nameToBeFilledTest = parser.parseFullName(atomisedNameStr, nomenclaturalCode, rank);
+            nameToBeFilledTest = parseWithExtension(parser, atomisedNameStr, rank, followingText, atomisedMap);
             if (nameToBeFilledTest.hasProblem()){
-                addProblemNameToFile("ato",atomisedNameStr,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
-                nameToBeFilledTest = parser.parseFullName(fullName, nomenclaturalCode,rank);
+                   addProblemNameToFile("ato",atomisedNameStr,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
+                nameToBeFilledTest = (TaxonName)parser.parseFullName(fullName, nomenclaturalCode,rank);
                 if (nameToBeFilledTest.hasProblem()){
                     addProblemNameToFile("full",fullName,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
                     parseNameManually=true;
                 }
             }
         }else{
-            nameToBeFilledTest = parser.parseFullName(fullName, nomenclaturalCode, rank);
+            nameToBeFilledTest = parseWithExtension(parser, fullName , rank, followingText, atomisedMap);
             if (nameToBeFilledTest.hasProblem()){
                 addProblemNameToFile("fullversion",fullName,nomenclaturalCode,rank, nameToBeFilledTest.getParsingProblems().toString());
-                nameToBeFilledTest = parser.parseFullName(fullName, nomenclaturalCode,rank);
+                nameToBeFilledTest = (TaxonName)parser.parseFullName(fullName, nomenclaturalCode,rank);
                 parseNameManually=true;
                 if(!originalName.equalsIgnoreCase(atomisedNameStr)) {
                     addNameDifferenceToFile(originalName,atomisedNameStr);
@@ -2801,13 +2607,72 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         else{
             createAtomisedTaxonString(newName, atomisedMap, myname);
             myname.setParsedName(nameToBeFilledTest);
-            myname.buildTaxon();
+            //TODO correct handling of createIfNotExists
+               myname.buildTaxon();
         }
         return myname;
 
     }
 
-    /**
+    private TaxonName parseWithExtension(INonViralNameParser parser, String atomisedNameStr, Rank rank, String followingText, HashMap<String, String> atomisedMap) {
+       Object[] nameExtensionResult = getPossibleExtension(followingText, atomisedMap, nomenclaturalCode);
+
+       TaxonName name = (TaxonName)parser.parseFullName(atomisedNameStr, nomenclaturalCode, rank);
+       if (nameExtensionResult != null && nameExtensionResult[0] != null){
+               String ext = (String)nameExtensionResult[0];
+               TaxonName extName = (TaxonName)parser.parseFullName(atomisedNameStr + " " + ext, nomenclaturalCode, rank);
+               if (! extName.hasProblem()){
+                       name = extName;
+                       this.usedFollowingTextPrefix = ext;
+                       //TODO do we need to fill the atomisedMap at all?
+                       if ((Boolean)(nameExtensionResult[1])){
+                               //TODO
+                       }
+                       if ((Boolean)(nameExtensionResult[2])){
+                               //TODO BasionymYear etc.
+                               Integer origYear = name.getPublicationYear();
+                               if (origYear != null){
+                                       atomisedMap.put(PUBLICATION_YEAR, origYear.toString());
+                               }
+                       }
+               }
+       }
+               return name;
+       }
+
+       private Object[] getPossibleExtension(String followingText, HashMap<String, String> atomisedMap, NomenclaturalCode nomenclaturalCode) {
+               if (StringUtils.isBlank(followingText)){
+                       return null;
+               }
+
+       boolean includeAuthor = true;
+       boolean includeYear = false;
+               if (atomisedMap.containsKey("dwc:scientificnameauthorship")){
+                       includeAuthor = false;
+               }
+       if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)){
+               includeYear = true;
+       }
+       String patternStr = "";
+       if (includeAuthor){
+               patternStr += NonViralNameParserImplRegExBase.capitalWord;
+       }
+       if (includeYear){
+               patternStr += "\\s*(,|\\s+)\\s*" + "(17|18|19|20)" + "\\d{2}" ;
+       }
+       String match = null;
+       if (! patternStr.isEmpty()){
+               Pattern pattern = Pattern.compile("^" + patternStr);
+               Matcher matcher = pattern.matcher(followingText.trim());
+               if (matcher.find()){
+                       match = matcher.group();
+               }
+       }
+
+               return new Object[]{match, includeAuthor, includeYear};
+       }
+
+       /**
      * @param atomisedName
      * @return
      */
@@ -2871,34 +2736,33 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
     private void addAtomisedNamesToMap(List<String> rankListToPrint, Rank rank, List<String> atomisedName, NodeList atom) {
         logger.info("addAtomisedNamesToMap");
         for (int k=0;k<atom.getLength();k++){
-            if (!atom.item(k).getNodeName().equalsIgnoreCase("dwc:taxonRank") ) {
-                if (atom.item(k).getNodeName().equalsIgnoreCase("dwc:subgenus") || atom.item(k).getNodeName().equalsIgnoreCase("dwcranks:subgenus")) {
-                    atomisedName.add("("+atom.item(k).getTextContent().trim()+")");
-                } else{
-                    if(atom.item(k).getNodeName().equalsIgnoreCase("dwcranks:varietyepithet") || atom.item(k).getNodeName().equalsIgnoreCase("dwc:Subspecies")) {
-                        if(atom.item(k).getNodeName().equalsIgnoreCase("dwcranks:varietyepithet")){
-                            atomisedName.add("var. "+atom.item(k).getTextContent().trim());
-                        }
-                        if(atom.item(k).getNodeName().equalsIgnoreCase("dwc:Subspecies") || atom.item(k).getNodeName().equalsIgnoreCase("dwc:infraspecificepithet")) {
+               Node node = atom.item(k);
+               String nodeName = node.getNodeName();
+            if (! nodeName.equalsIgnoreCase("dwc:taxonRank") ) {  //rank has been handled in higher method
+                if (nodeName.equalsIgnoreCase("dwc:subgenus") || nodeName.equalsIgnoreCase("dwcranks:subgenus")) {
+                    atomisedName.add("("+ node.getTextContent().trim()+")");
+                } else if(nodeName.equalsIgnoreCase("dwcranks:varietyepithet") || nodeName.equalsIgnoreCase("dwc:Subspecies") || nodeName.equalsIgnoreCase("dwc:infraspecificepithet")) {
+                               if(nodeName.equalsIgnoreCase("dwcranks:varietyepithet")){
+                            atomisedName.add("var. "+node.getTextContent().trim());
+                        }else if(nodeName.equalsIgnoreCase("dwc:Subspecies") || nodeName.equalsIgnoreCase("dwc:infraspecificepithet")) {
                             atomisedName.add("subsp. "+atom.item(k).getTextContent().trim());
                         }
-                    }
-                    else{
-                        if(rankListToPrint.contains(atom.item(k).getNodeName().toLowerCase())) {
-                            atomisedName.add(atom.item(k).getTextContent().trim());
-                        }
-                        else{
-                            //                                    System.out.println("rank : "+rank.toString());
-                            if (rank.isHigher(Rank.GENUS()) && (atom.item(k).getNodeName().indexOf("dwcranks:")>-1 || atom.item(k).getNodeName().indexOf("dwc:Family")>-1)) {
-                                atomisedName.add(atom.item(k).getTextContent().trim());
-                            }
-                            //                                    else{
-                            //                                      System.out.println("on a oublie qqn "+atom.item(k).getNodeName());
-                            //                                  }
-                        }
-                        //                                else{
-                        //                                    System.out.println("on a oublie qqn "+atom.item(k).getNodeName());
-                        //                                }
+                } else if(rankListToPrint.contains(nodeName.toLowerCase())) {
+                    atomisedName.add(node.getTextContent().trim());
+                } else{
+                    if (rank.isHigher(Rank.GENUS()) && (nodeName.indexOf("dwcranks:")>-1 || nodeName.indexOf("dwc:Family")>-1)) {
+                        atomisedName.add(node.getTextContent().trim());
+                    }else if (nodeName.equals("#text")){
+                       String text = node.getTextContent();
+                       if (StringUtils.isNotBlank(text)){
+                               //TODO handle text
+                               logger.warn("name xmldata contains text. This is unhandled");
+                       }
+                    }else if (nodeName.matches("(?i)(dwc:Kingdom|dwc:Class|dwc:Order|dwc:Family)")){
+                       //we currently do not use higher ranks information
+                    }else{
+                       //TODO handle unhandled node
+                       logger.warn("Unhandled node: " + nodeName);
                     }
                 }
             }
@@ -2937,8 +2801,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myname
      * @return
      */
-    private String extractAuthorFromNames(Rank rank, String name, HashMap<String, String> atomisedMap,
-            MyName myname) {
+    private String extractAuthorFromNames(Rank rank, String name, HashMap<String, String> atomisedMap, MyName myname) {
         logger.info("extractAuthorFromNames");
         String fullName=name;
         if (atomisedMap.get("dwc:scientificnameauthorship") == null && fullName!=null){
@@ -3043,8 +2906,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             }
             n=n.trim();
             String author = myname.getAuthor();
-            if(n.split(" ").length>2)
-            {
+            if(n.split(" ").length>2){
+
                 String n2=n.split(" ")[0]+" "+n.split(" ")[1];
                 String a= "";
                 try{
@@ -3073,89 +2936,167 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         if(atomisedMap.get("dwcranks:formepithet") != null && checkRankValidForImport(Rank.FORM())){
             myname.setFormStr(atomisedMap.get("dwcranks:formepithet"));
         }
+        if (atomisedMap.get(PUBLICATION_YEAR) != null){
+               myname.setPublicationYear(Integer.valueOf(atomisedMap.get(PUBLICATION_YEAR)));
+        }
     }
 
-    private void createSynonym(Rank rank, String newName, HashMap<String, String> atomisedMap, MyName myname) {
+    /**
+     * @see #createUnparsedSynonymNew(Rank, String, HashMap, MyName)
+     * @param rank
+     * @param newName
+     * @param atomisedMap
+     * @param myname
+     */
+    private void createUnparsedSynonym(Rank rank, String newName, HashMap<String, String> atomisedMap, MyName myname) {
         logger.info("createSynonym");
         //System.out.println("createsynonym");
         if(rank.equals(Rank.UNKNOWN_RANK())){
             myname.setNotParsableTaxon(newName);
-        }else
-        {if(atomisedMap.get("dwc:family") != null && checkRankValidForImport(Rank.FAMILY()) && rank.equals(Rank.FAMILY())){
-            myname.setFamily(myname.findOrCreateTaxon(atomisedMap.get("dwc:family"),newName, Rank.FAMILY(),rank));
-        }
-        if(atomisedMap.get("dwcranks:subfamily") != null  && checkRankValidForImport(Rank.SUBFAMILY()) && rank.equals(Rank.SUBFAMILY())){
-            myname.setSubfamily(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:subfamily"), newName,Rank.SUBFAMILY(),rank));
-        }
-        if(atomisedMap.get("dwcranks:tribe") != null && checkRankValidForImport(Rank.TRIBE()) && rank.equals(Rank.TRIBE())){
-            myname.setTribe(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:tribe"),newName, Rank.TRIBE(),rank));
-        }
-        if(atomisedMap.get("dwcranks:subtribe") != null && checkRankValidForImport(Rank.SUBTRIBE()) && rank.equals(Rank.SUBTRIBE())){
-            myname.setSubtribe(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:subtribe"),newName, Rank.SUBTRIBE(),rank));
-        }
-        if(atomisedMap.get("dwc:genus") != null && checkRankValidForImport(Rank.GENUS()) && rank.equals(Rank.GENUS())){
-            myname.setGenus(myname.findOrCreateTaxon(atomisedMap.get("dwc:genus"),newName, Rank.GENUS(),rank));
-        }
-        if(atomisedMap.get("dwcranks:subgenus") != null && checkRankValidForImport(Rank.SUBGENUS()) && rank.equals(Rank.SUBGENUS())){
-            myname.setSubgenus(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:subgenus"),newName, Rank.SUBGENUS(),rank));
-        }
-        if(atomisedMap.get("dwc:subgenus") != null && checkRankValidForImport(Rank.SUBGENUS()) && rank.equals(Rank.SUBGENUS())){
-            myname.setSubgenus(myname.findOrCreateTaxon(atomisedMap.get("dwc:subgenus"),newName, Rank.SUBGENUS(),rank));
+        }else{
+               if(atomisedMap.get("dwc:family") != null && checkRankValidForImport(Rank.FAMILY()) && rank.equals(Rank.FAMILY())){
+                   myname.setFamily(myname.findOrCreateTaxon(atomisedMap.get("dwc:family"),newName, Rank.FAMILY(),rank));
+               }
+               if(atomisedMap.get("dwcranks:subfamily") != null  && checkRankValidForImport(Rank.SUBFAMILY()) && rank.equals(Rank.SUBFAMILY())){
+                   myname.setSubfamily(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:subfamily"), newName,Rank.SUBFAMILY(),rank));
+               }
+               if(atomisedMap.get("dwcranks:tribe") != null && checkRankValidForImport(Rank.TRIBE()) && rank.equals(Rank.TRIBE())){
+                   myname.setTribe(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:tribe"),newName, Rank.TRIBE(),rank));
+               }
+               if(atomisedMap.get("dwcranks:subtribe") != null && checkRankValidForImport(Rank.SUBTRIBE()) && rank.equals(Rank.SUBTRIBE())){
+                   myname.setSubtribe(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:subtribe"),newName, Rank.SUBTRIBE(),rank));
+               }
+               if(atomisedMap.get("dwc:genus") != null && checkRankValidForImport(Rank.GENUS()) && rank.equals(Rank.GENUS())){
+                   myname.setGenus(myname.findOrCreateTaxon(atomisedMap.get("dwc:genus"),newName, Rank.GENUS(),rank));
+               }
+               if(atomisedMap.get("dwcranks:subgenus") != null && checkRankValidForImport(Rank.SUBGENUS()) && rank.equals(Rank.SUBGENUS())){
+                   myname.setSubgenus(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:subgenus"),newName, Rank.SUBGENUS(),rank));
+               }
+               if(atomisedMap.get("dwc:subgenus") != null && checkRankValidForImport(Rank.SUBGENUS()) && rank.equals(Rank.SUBGENUS())){
+                   myname.setSubgenus(myname.findOrCreateTaxon(atomisedMap.get("dwc:subgenus"),newName, Rank.SUBGENUS(),rank));
+               }
+               if(atomisedMap.get("dwc:species") != null && checkRankValidForImport(Rank.SPECIES()) && rank.equals(Rank.SPECIES())){
+                   String n=newName;
+                   if(atomisedMap.get("dwc:infraspecificepithet") != null) {
+                       n=newName.split(atomisedMap.get("dwc:infraspecificepithet"))[0];
+                       n=n.replace("subsp.","");
+                   }
+                   if(atomisedMap.get("dwc:subspecies") != null) {
+                       n=newName.split(atomisedMap.get("dwc:subspecies"))[0];
+                       n=n.replace("subsp.","");
+                   }
+                   if(atomisedMap.get("dwcranks:varietyepithet") != null) {
+                       n=newName.split(atomisedMap.get("dwcranks:varietyepithet"))[0];
+                       n=n.replace("var.","");
+                       n=n.replace("v.","");
+                   }
+                   if(atomisedMap.get("dwcranks:formepithet") != null) {
+                       //TODO
+                       //System.out.println("TODO FORMA");
+                       n=newName.split(atomisedMap.get("dwcranks:formepithet"))[0];
+                       n=n.replace("forma","");
+                   }
+                   n=n.trim();
+                   String author = myname.getAuthor();
+                   if(n.split(" ").length>2){
+
+                       String n2=n.split(" ")[0]+" "+n.split(" ")[1];
+                       String a="";
+                       try{
+                           a= n.split(n2)[1].trim();
+                       }catch(Exception e){logger.info("no author in "+n);}
+                       myname.setAuthor(a);
+                       //System.out.println("FINDCREATESPECIES --"+n2+"--"+n+"**"+a+"##");
+                       n=n2;
+
+                   }
+                   Taxon species = myname.findOrCreateTaxon(atomisedMap.get("dwc:species"),n, Rank.SPECIES(),rank);
+                   myname.setSpecies(species);
+                   myname.setAuthor(author);
+               }
+               if(atomisedMap.get("dwc:subspecies") != null && checkRankValidForImport(Rank.SUBSPECIES()) && rank.equals(Rank.SUBSPECIES())){
+                   myname.setSubspecies(myname.findOrCreateTaxon(atomisedMap.get("dwc:subspecies"), newName,Rank.SUBSPECIES(),rank));
+               }
+               if(atomisedMap.get("dwc:infraspecificepithet") != null && checkRankValidForImport(Rank.SUBSPECIES()) && rank.equals(Rank.SUBSPECIES())){
+                   myname.setSubspecies(myname.findOrCreateTaxon(atomisedMap.get("dwc:infraspecificepithet"),newName, Rank.SUBSPECIES(),rank));
+               }
+               if(atomisedMap.get("dwcranks:varietyepithet") != null && checkRankValidForImport(Rank.VARIETY()) && rank.equals(Rank.VARIETY())){
+                   myname.setVariety(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:varietyepithet"),newName, Rank.VARIETY(),rank));
+               }
+               if(atomisedMap.get("dwcranks:formepithet") != null && checkRankValidForImport(Rank.FORM()) && rank.equals(Rank.FORM())){
+                   myname.setForm(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:formepithet"), newName,Rank.FORM(),rank));
+               }
         }
-        if(atomisedMap.get("dwc:species") != null && checkRankValidForImport(Rank.SPECIES()) && rank.equals(Rank.SPECIES())){
-            String n=newName;
-            if(atomisedMap.get("dwc:infraspecificepithet") != null) {
-                n=newName.split(atomisedMap.get("dwc:infraspecificepithet"))[0];
-                n=n.replace("subsp.","");
-            }
-            if(atomisedMap.get("dwc:subspecies") != null) {
-                n=newName.split(atomisedMap.get("dwc:subspecies"))[0];
-                n=n.replace("subsp.","");
-            }
-            if(atomisedMap.get("dwcranks:varietyepithet") != null) {
-                n=newName.split(atomisedMap.get("dwcranks:varietyepithet"))[0];
-                n=n.replace("var.","");
-                n=n.replace("v.","");
-            }
-            if(atomisedMap.get("dwcranks:formepithet") != null) {
-                //TODO
-                //System.out.println("TODO FORMA");
-                n=newName.split(atomisedMap.get("dwcranks:formepithet"))[0];
-                n=n.replace("forma","");
-            }
-            n=n.trim();
-            String author = myname.getAuthor();
-            if(n.split(" ").length>2)
-            {
-                String n2=n.split(" ")[0]+" "+n.split(" ")[1];
-                String a="";
-                try{
-                    a= n.split(n2)[1].trim();
-                }catch(Exception e){logger.info("no author in "+n);}
-                myname.setAuthor(a);
-                //System.out.println("FINDCREATESPECIES --"+n2+"--"+n+"**"+a+"##");
-                n=n2;
 
-            }
+    }
 
-            myname.setSpecies(myname.findOrCreateTaxon(atomisedMap.get("dwc:species"),n, Rank.SPECIES(),rank));
-            myname.setAuthor(author);
-        }
-        if(atomisedMap.get("dwc:subspecies") != null && checkRankValidForImport(Rank.SUBSPECIES()) && rank.equals(Rank.SUBSPECIES())){
-            myname.setSubspecies(myname.findOrCreateTaxon(atomisedMap.get("dwc:subspecies"), newName,Rank.SUBSPECIES(),rank));
-        }
-        if(atomisedMap.get("dwc:infraspecificepithet") != null && checkRankValidForImport(Rank.SUBSPECIES()) && rank.equals(Rank.SUBSPECIES())){
-            myname.setSubspecies(myname.findOrCreateTaxon(atomisedMap.get("dwc:infraspecificepithet"),newName, Rank.SUBSPECIES(),rank));
-        }
-        if(atomisedMap.get("dwcranks:varietyepithet") != null && checkRankValidForImport(Rank.VARIETY()) && rank.equals(Rank.VARIETY())){
-            myname.setVariety(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:varietyepithet"),newName, Rank.VARIETY(),rank));
-        }
-        if(atomisedMap.get("dwcranks:formepithet") != null && checkRankValidForImport(Rank.FORM()) && rank.equals(Rank.FORM())){
-            myname.setForm(myname.findOrCreateTaxon(atomisedMap.get("dwcranks:formepithet"), newName,Rank.FORM(),rank));
-        }
-        }
 
-    }
+    /**
+     * @param refMods
+     * @see #createUnparsedSynonym(Rank, String, HashMap, MyName)
+     * the original TaxonXImport extracted Synonyms by creating acc Taxa with partial names
+     * I (AM) do not understand this but don't want to destroy code which maybe works in some cases) there
+     * I created this switch for old
+     * for Spiders the new version is preferred
+     */
+    private void createUnparsedSynonymNew(Rank rank, String newName, HashMap<String, String> atomisedMap, MyName myname, Reference refMods) {
+        logger.info("createSynonym");
+
+        INonViralName nameToBeFilled = this.getNonViralNameAccNomenclature();
+        //System.out.println("createsynonym");
+        if(rank.equals(Rank.UNKNOWN_RANK())){
+            //TODO
+               myname.setNotParsableTaxon(newName);
+
+               nameToBeFilled.setTitleCache(newName, true);
+        }else{
+               if(atomisedMap.get("dwc:genus") != null ){
+                       nameToBeFilled.setGenusOrUninomial(atomisedMap.get("dwc:genus"));
+               }
+               if (rank.isSupraGeneric()){
+                       if (atomisedMap.get("dwcranks:subtribe") != null ){
+                       nameToBeFilled.setGenusOrUninomial(atomisedMap.get("dwcranks:subtribe"));
+               }else if (atomisedMap.get("dwcranks:subtribe") != null ){
+                       nameToBeFilled.setGenusOrUninomial(atomisedMap.get("dwcranks:subtribe"));
+               }else if (atomisedMap.get("dwcranks:tribe") != null ){
+                       nameToBeFilled.setGenusOrUninomial(atomisedMap.get("dwcranks:tribe"));
+               }else if (atomisedMap.get("dwcranks:subfamily") != null ){
+                       nameToBeFilled.setGenusOrUninomial(atomisedMap.get("dwcranks:subfamily"));
+               }else if (atomisedMap.get("dwc:family") != null ){
+                       nameToBeFilled.setGenusOrUninomial(atomisedMap.get("dwc:family"));
+                   }else{
+                       logger.warn("Supra generic rank not yet handled or atomisation not available");
+                   }
+               }
+               if (atomisedMap.get("dwcranks:subgenus") != null){
+                       nameToBeFilled.setInfraGenericEpithet(atomisedMap.get("dwcranks:subgenus"));
+               }
+               if (atomisedMap.get("dwc:subgenus") != null){
+                       nameToBeFilled.setInfraGenericEpithet(atomisedMap.get("dwc:subgenus"));
+               }
+               if (atomisedMap.get("dwc:species") != null){
+                       nameToBeFilled.setSpecificEpithet(atomisedMap.get("dwc:species"));
+               }
+               if (atomisedMap.get("dwcranks:formepithet") != null){
+                       nameToBeFilled.setInfraSpecificEpithet(atomisedMap.get("dwcranks:formepithet"));
+               }else if (atomisedMap.get("dwcranks:varietyepithet") != null){
+                       nameToBeFilled.setInfraSpecificEpithet(atomisedMap.get("dwcranks:varietyepithet"));
+               }else if (atomisedMap.get("dwc:infraspecificepithet") != null){
+                       nameToBeFilled.setInfraSpecificEpithet(atomisedMap.get("dwc:infraspecificepithet"));
+               }else if (atomisedMap.get("dwc:subspecies") != null){
+                       nameToBeFilled.setInfraSpecificEpithet(atomisedMap.get("dwc:subspecies"));
+               }
+            Reference sec = sourceUrlRef;
+            if(!state2.getConfig().doKeepOriginalSecundum()){
+                sec = state2.getConfig().getSecundum();
+            }
+               Synonym syn = Synonym.NewInstance(nameToBeFilled, sec);
+//             sourceHandler.addSource(refMods, syn);
+               myname.setSyno(syn);
+               myname.setSynonym(true);
+        }
+       }
+
     /**
      * @param rank
      * @param newName
@@ -3212,8 +3153,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 }
                 n=n.trim();
                 String author = myname.getAuthor();
-                if(n.split(" ").length>2)
-                {
+                if(n.split(" ").length>2){
                     String n2=n.split(" ")[0]+" "+n.split(" ")[1];
                     String a="";
                     try{
@@ -3248,7 +3188,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
     private boolean checkRankValidForImport(Rank currentRank) {
         //logger.info("checkRankValidForImport");
-        return currentRank.isLower(configState.getConfig().getMaxRank()) || currentRank.equals(configState.getConfig().getMaxRank());
+        return currentRank.isLower(state2.getConfig().getMaxRank()) || currentRank.equals(state2.getConfig().getMaxRank());
     }
 
 
@@ -3261,74 +3201,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         classification = classification2;
     }
 
-    /**
-     * @param tnb
-     * cast the current taxonnamebase into a botanical name or zoological or bacterial name
-     * if errors, cast into a classis nonviralname
-     * @param taxonnamebase2
-     */
-    @SuppressWarnings("rawtypes")
-    public NonViralName<?> castTaxonNameBase(TaxonNameBase tnb, NonViralName<?> nvn) {
-        //logger.info("castTaxonNameBase");
-        NonViralName<?> taxonnamebase2 = nvn;
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICNAFP)) {
-            try{
-                taxonnamebase2=(BotanicalName) tnb;
-            }catch(Exception e){
-                taxonnamebase2= (NonViralName<?>) tnb;
-            }
-        }
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)) {
-            try{
-                taxonnamebase2=(ZoologicalName) tnb;
-            }catch(Exception e){
-                taxonnamebase2= (NonViralName<?>) tnb;
-            }
-        }
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICNB)) {
-            try{
-                taxonnamebase2=(BacterialName) tnb;
-            }catch(Exception e){
-                taxonnamebase2= (NonViralName<?>) tnb;
-            }
-        }
-        return taxonnamebase2;
-    }
 
-    /**
-     * @param tnb
-     * cast the current taxonnamebase into a botanical name or zoological or bacterial name
-     * if errors, cast into a classis nonviralname
-     * @param taxonnamebase2
-     */
-    @SuppressWarnings("rawtypes")
-    public NonViralName<?> castTaxonNameBase(TaxonNameBase tnb) {
-        //logger.info("castTaxonNameBase2");
-        NonViralName<?> taxonnamebase2 = null;
-        tnb=CdmBase.deproxy(tnb, TaxonNameBase.class);
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICNAFP)) {
-            try{
-                taxonnamebase2=(BotanicalName) tnb;
-            }catch(Exception e){
-                taxonnamebase2= (NonViralName<?>) tnb;
-            }
-        }
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICZN)) {
-            try{
-                taxonnamebase2=(ZoologicalName) tnb;
-            }catch(Exception e){
-                taxonnamebase2= (NonViralName<?>) tnb;
-            }
-        }
-        if (nomenclaturalCode.equals(NomenclaturalCode.ICNB)) {
-            try{
-                taxonnamebase2=(BacterialName) tnb;
-            }catch(Exception e){
-                taxonnamebase2= (NonViralName<?>) tnb;
-            }
-        }
-        return taxonnamebase2;
-    }
 
     public class MyName {
         /**
@@ -3346,14 +3219,17 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         String status="";
         String author=null;
 
-        NonViralName<?> taxonnamebase;
+        TaxonName taxonName;
 
-        Reference<?> refMods ;
+        Reference refMods ;
 
         Taxon family,subfamily,tribe,subtribe,genus,subgenus,species,subspecies, variety,form;
-        NonViralName<?> familyName, subfamilyName, tribeName,subtribeName,genusName,subgenusName,speciesName,subspeciesName;
+        INonViralName familyName, subfamilyName, tribeName,subtribeName,genusName,subgenusName,speciesName,subspeciesName;
         String familyStr, subfamilyStr, tribeStr,subtribeStr,genusStr,subgenusStr,speciesStr,subspeciesStr,formStr,varietyStr;
-        Taxon higherTaxa;
+        Integer publicationYear;
+
+
+               Taxon higherTaxa;
         Rank higherRank;
         private Taxon taxon;
         private Synonym syno;
@@ -3401,7 +3277,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             this.isSynonym = isSynonym;
         }
 
-        public void setSource(Reference<?> re){
+        public void setSource(Reference re){
             refMods=re;
         }
 
@@ -3536,6 +3412,14 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             return varietyStr;
         }
 
+        public Integer getPublicationYear() {
+                       return publicationYear;
+               }
+
+               public void setPublicationYear(Integer publicationYear) {
+                       this.publicationYear = publicationYear;
+               }
+
         /**
          * @param newName2
          */
@@ -3552,37 +3436,33 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     logger.warn("Problem with status");
                 }
             }
-            List<TaxonBase> tmpList = new ArrayList<TaxonBase>();
+            List<TaxonBase> tmpList = new ArrayList<>();
 
-            Pager<TaxonBase> taxontest = importer.getTaxonService().findByTitle(TaxonBase.class, newName2, MatchMode.BEGINNING, null, null, null, null, null);
+            Pager<TaxonBase> taxontest = importer.getTaxonService().findByTitleWithRestrictions(TaxonBase.class, newName2, MatchMode.BEGINNING, null, null, null, null, null);
             tmpList.addAll(taxontest.getRecords());
 
             //logger.info("tmpList returned: "+tmpList.size());
 
 
+            INonViralName identicName = null;
             boolean foundIdentic=false;
-            TaxonBase<?> tmptaxonbase=null;
+            TaxonBase<?> tmpTaxonBase=null;
             //            Taxon tmpPartial=null;
             for (TaxonBase<?> tmpb:tmpList){
                 if(tmpb !=null){
-                    TaxonNameBase<?,?> tnb =  tmpb.getName();
+                    TaxonName tnb =  tmpb.getName();
                     Rank crank=null;
                     if (tnb != null){
                         if (tnb.getTitleCache().split("sec.")[0].trim().equalsIgnoreCase(newName2) ){
                             crank =tnb.getRank();
                             if (crank !=null && rank !=null){
                                 if (crank.equals(rank)){
-                                    foundIdentic=true;
-                                    try{
-                                        if(!isSynonym) {
-                                            tmptaxonbase=tmpb;
-                                        } else {
-                                            tmptaxonbase=tmpb;
-                                        }
-                                        break;
-                                    }catch(Exception e){
-                                        e.printStackTrace();
-                                    }
+                                       identicName = tnb;
+                                       if (isSynonym && tmpb.isInstanceOf(Synonym.class) || !isSynonym && tmpb.isInstanceOf(Taxon.class)){
+                                               foundIdentic=true;
+                                               tmpTaxonBase=tmpb;
+                                                       break;
+                                       }
                                 }
                             }
                         }
@@ -3591,66 +3471,68 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             }
             boolean statusMatch=false;
             boolean appendedMatch=false;
-            if(tmptaxonbase !=null && foundIdentic){
-                statusMatch=compareStatus(tmptaxonbase, statusType);
-                if (!getStatus().isEmpty() && ! (tmptaxonbase.getAppendedPhrase() == null)) {
-                    appendedMatch=tmptaxonbase.getAppendedPhrase().equals(getStatus());
+            if(tmpTaxonBase !=null && foundIdentic){
+                statusMatch=compareStatus(tmpTaxonBase, statusType);
+                if (!getStatus().isEmpty() && ! (tmpTaxonBase.getAppendedPhrase() == null)) {
+                    appendedMatch=tmpTaxonBase.getAppendedPhrase().equals(getStatus());
                 }
-                if (getStatus().isEmpty() && tmptaxonbase.getAppendedPhrase() == null) {
+                if (getStatus().isEmpty() && tmpTaxonBase.getAppendedPhrase() == null) {
                     appendedMatch=true;
                 }
 
             }
-            if ((tmptaxonbase == null || !foundIdentic) ||  (tmptaxonbase != null && !statusMatch) ||  (tmptaxonbase != null && !appendedMatch && !statusMatch)){
+            if ((tmpTaxonBase == null || !foundIdentic) ||  (tmpTaxonBase != null && !statusMatch) ||  (tmpTaxonBase != null && !appendedMatch && !statusMatch)){
 
-                NonViralName<?> tnb = getNonViralNameAccNomenclature();
-                tnb.setRank(rank);
+               INonViralName tnb;
+               if (identicName == null){
+                       tnb = getNonViralNameAccNomenclature();
+                       tnb.setRank(rank);
 
-                if(statusType != null) {
-                    tnb.addStatus(NomenclaturalStatus.NewInstance(statusType));
-                }
-                if(getStatus()!=null) {
-                    tnb.setAppendedPhrase(getStatus());
-                }
+                       if(statusType != null) {
+                           tnb.addStatus(NomenclaturalStatus.NewInstance(statusType));
+                       }
+                       if(StringUtils.isNotBlank(getStatus())) {
+                           tnb.setAppendedPhrase(getStatus());
+                       }
+                       tnb.setTitleCache(newName2,true);
+                       tmpTaxonBase = findMatchingTaxon(tnb,refMods);
+                   }else{
+                       tnb = identicName;
+               }
 
-                tnb.setTitleCache(newName2,true);
-                tmptaxonbase = findMatchingTaxon(tnb,refMods);
-                if(tmptaxonbase==null){
-                    tmptaxonbase=Taxon.NewInstance(tnb, refMods);
-                    if(!configState.getConfig().doKeepOriginalSecundum()) {
-                        tmptaxonbase.setSec(configState.getConfig().getSecundum());
+                if(tmpTaxonBase==null){
+                    tmpTaxonBase = isSynonym ? Synonym.NewInstance(tnb, refMods) : Taxon.NewInstance(tnb, refMods);
+                    if(!state2.getConfig().doKeepOriginalSecundum()) {
+                        tmpTaxonBase.setSec(state2.getConfig().getSecundum());
                     }
-                    //                    tmptaxonbase.setSec(refMods);
+                    //tmptaxonbase.setSec(refMods);
                     if(!isSynonym) {
-                        classification.addChildTaxon((Taxon)tmptaxonbase, null, null);
-                        sourceHandler.addSource(refMods, (Taxon)tmptaxonbase);
+                        classification.addChildTaxon((Taxon)tmpTaxonBase, null, null);
+                        sourceHandler.addSource(refMods, (Taxon)tmpTaxonBase);
                     }
                 }
             }
-            if(!isSynonym) {
-                tmptaxonbase = CdmBase.deproxy(tmptaxonbase, Taxon.class);
-            } else {
-                tmptaxonbase = CdmBase.deproxy(tmptaxonbase, Synonym.class);
-            }
+
+            tmpTaxonBase = CdmBase.deproxy(tmpTaxonBase, TaxonBase.class);
             if (author != null) {
                 if (!getIdentifier().isEmpty() && (getIdentifier().length()>2)){
-                    setLSID(getIdentifier(), tmptaxonbase);
-                    importer.getTaxonService().saveOrUpdate(tmptaxonbase);
-                    if(!isSynonym) {
-                        tmptaxonbase = CdmBase.deproxy(tmptaxonbase, Taxon.class);
-                    } else {
-                        tmptaxonbase = CdmBase.deproxy(tmptaxonbase, Synonym.class);
-                    }
+                    setLSID(getIdentifier(), tmpTaxonBase);
+                    importer.getTaxonService().saveOrUpdate(tmpTaxonBase);
+                    tmpTaxonBase = CdmBase.deproxy(tmpTaxonBase, TaxonBase.class);
                 }
             }
-            TaxonNameBase<?,?> tnb = CdmBase.deproxy(tmptaxonbase.getName(), TaxonNameBase.class);
+            TaxonName tnb = CdmBase.deproxy(tmpTaxonBase.getName(), TaxonName.class);
 
             if(!isSynonym) {
-                this.taxon=(Taxon)tmptaxonbase;
+                this.taxon=(Taxon)tmpTaxonBase;
             } else {
-                this.syno=(Synonym)tmptaxonbase;
+                if (tmpTaxonBase instanceof Taxon){
+                       logger.warn("Incorrect status");
+                }
+               this.syno=(Synonym)tmpTaxonBase;
             }
-            castTaxonNameBase(tnb, taxonnamebase);
+
+            taxonName = tnb;
 
         }
 
@@ -3662,60 +3544,63 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             logger.info("buildTaxon");
             NomenclaturalStatusType statusType = null;
             if (!getStatus().isEmpty()){
-                try {
-                    statusType = nomStatusString2NomStatus(getStatus());
-                    taxonnamebase.addStatus(NomenclaturalStatus.NewInstance(statusType));
-                } catch (UnknownCdmTypeException e) {
-                    addProblematicStatusToFile(getStatus());
-                    logger.warn("Problem with status");
-                }
-            }
-            importer.getNameService().save(taxonnamebase);
-
-            TaxonBase<?> tmptaxonbase;
+               status = getStatus();
+               String newNameStatus = newNameStatus(status);
+               if (newNameStatus != null){
+                       taxonName.setAppendedPhrase(newNameStatus);
+               }else{
+                       try {
+                               statusType = nomStatusString2NomStatus(getStatus());
+                               taxonName.addStatus(NomenclaturalStatus.NewInstance(statusType));
+                       } catch (UnknownCdmTypeException e) {
+                               addProblematicStatusToFile(getStatus());
+                               logger.warn("Problem with status");
+                       }
+               }
+            }
+            importer.getNameService().save(taxonName);
+
+            TaxonBase<?> tmpTaxonBase;
             if (!isSynonym) {
-                tmptaxonbase =Taxon.NewInstance(taxonnamebase, refMods); //sec set null
+                tmpTaxonBase =Taxon.NewInstance(taxonName, refMods); //sec set null
             }
             else {
-                tmptaxonbase =Synonym.NewInstance(taxonnamebase, refMods); //sec set null
+                tmpTaxonBase =Synonym.NewInstance(taxonName, refMods); //sec set null
             }
             boolean exist = false;
-            for (TaxonNode p : classification.getAllNodes()){
-                try{
-                    if(p.getTaxon().getTitleCache().equalsIgnoreCase(tmptaxonbase.getTitleCache())) {
-                        if(compareStatus(p.getTaxon(), statusType)){
-                            try{
-                                if (!isSynonym) {
-                                    tmptaxonbase=CdmBase.deproxy(p.getTaxon(), Taxon.class);
-                                } else {
-                                    tmptaxonbase=CdmBase.deproxy(p.getTaxon(), Synonym.class);
-                                }
+            if (!isSynonym){
+                   for (TaxonNode node : classification.getAllNodes()){
+                       try{
+                               Taxon nodeTaxon = node.getTaxon();
+                               boolean titleMatches = nodeTaxon.getTitleCache().equalsIgnoreCase(tmpTaxonBase.getTitleCache());
+                               boolean nomStatusMatches = compareStatus(node.getTaxon(), statusType);
+                               boolean nodeNameReplaceable = checkNodeNameReplaceable(nodeTaxon, tmpTaxonBase);
+                           if(titleMatches && nomStatusMatches) {
+                               if (!isSynonym) {
+                                       tmpTaxonBase=CdmBase.deproxy(nodeTaxon, TaxonBase.class);
+                                   exist =true;
+                               } else {
+                                   logger.info("Found the same name but from another type (taxon/synonym)");
+                                   TaxonName existingTnb = getTaxon().getName();
+                                tmpTaxonBase = Synonym.NewInstance(existingTnb, refMods);
+                                importer.getTaxonService().saveOrUpdate(tmpTaxonBase);
                                 exist =true;
-                            }catch(Exception e){
-                                logger.warn("Found the same name but from another type (taxon/synonym)");
-                                TaxonNameBase<?,?> existingTnb = getTaxon().getName();
-                                if (isSynonym){
-                                    tmptaxonbase = new Synonym(existingTnb, refMods);
-                                    importer.getTaxonService().saveOrUpdate(tmptaxonbase);
-                                    tmptaxonbase=CdmBase.deproxy(tmptaxonbase, Synonym.class);
-                                    exist =true;
-                                }
-                                else{
-                                    tmptaxonbase = new Taxon(existingTnb, refMods);
-                                }
                             }
-                        }
-                    }
-                }catch(NullPointerException n){logger.warn(" A taxon is either null or its titlecache is null - ignore it?");}
+                           }else if (nodeNameReplaceable){
+                               nodeTaxon.setName(tmpTaxonBase.getName());
+                               tmpTaxonBase = nodeTaxon;
+                               exist = true;
+                           }
+                       }catch(NullPointerException n){logger.warn(" A taxon is either null or its titlecache is null - ignore it?");}
+                   }
             }
             if (!exist){
 
                 boolean insertAsExisting =false;
                 List<Taxon> existingTaxons=new ArrayList<Taxon>();
                 try {
-                    existingTaxons = getMatchingTaxon(taxonnamebase);
+                    existingTaxons = getMatchingTaxa(taxonName);
                 } catch (Exception e1) {
-                    // TODO Auto-generated catch block
                     e1.printStackTrace();
                 }
                 double similarityScore=0.0;
@@ -3724,27 +3609,22 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 String author2="";
                 String t1="";
                 String t2="";
-                for (Taxon bestMatchingTaxon:existingTaxons){
-                    //System.out.println("tnbase "+taxonnamebase.getTitleCache());
+                for (Taxon bestMatchingTaxon : existingTaxons){
+                    //System.out.println("tnbase "+taxonname.getTitleCache());
                     //System.out.println("bestex "+bestMatchingTaxon.getTitleCache());
-                    try {
-                        if(taxonnamebase.getAuthorshipCache()!=null) {
-                            author1=taxonnamebase.getAuthorshipCache();
-                        }
-                    } catch (Exception e) {
-                        // TODO Auto-generated catch block
-                        e.printStackTrace();
+                    if(taxonName.getAuthorshipCache()!=null) {
+                       author1=taxonName.getAuthorshipCache();
                     }
                     try {
-                        if(castTaxonNameBase(bestMatchingTaxon.getName()).getAuthorshipCache()!=null) {
-                            author2=castTaxonNameBase(bestMatchingTaxon.getName()).getAuthorshipCache();
+                        if(bestMatchingTaxon.getName().getAuthorshipCache()!=null) {
+                            author2=bestMatchingTaxon.getName().getAuthorshipCache();
                         }
                     } catch (Exception e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
                     }
                     try {
-                        t1=taxonnamebase.getTitleCache().split("sec.")[0].trim();
+                        t1=taxonName.getTitleCache();
                         if (author1!=null && !StringUtils.isEmpty(author1)) {
                             t1=t1.split(Pattern.quote(author1))[0];
                         }
@@ -3766,35 +3646,35 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     //System.out.println("taxonscore "+similarityScore);
                     similarityAuthor=similarity(author1.trim(), author2.trim());
                     //System.out.println("authorscore "+similarityAuthor);
-                    insertAsExisting = compareAndCheckTaxon(taxonnamebase, refMods, similarityScore, bestMatchingTaxon,similarityAuthor);
+                    insertAsExisting = compareAndCheckTaxon(taxonName, refMods, similarityScore, bestMatchingTaxon, similarityAuthor);
                     if(insertAsExisting) {
-                        tmptaxonbase=bestMatchingTaxon;
+                        tmpTaxonBase=bestMatchingTaxon;
                         break;
                     }
                 }
-                if (!insertAsExisting){
-                    if(!configState.getConfig().doKeepOriginalSecundum()) {
-                        tmptaxonbase.setSec(configState.getConfig().getSecundum());
+                if ( !insertAsExisting ){
+                    if(!state2.getConfig().doKeepOriginalSecundum()) {
+                        tmpTaxonBase.setSec(state2.getConfig().getSecundum());
                     }
 
                     //                    tmptaxonbase.setSec(refMods);
-                    if (taxonnamebase.getRank().equals(configState.getConfig().getMaxRank())) {
+                    if (taxonName.getRank().equals(state2.getConfig().getMaxRank())) {
                         //System.out.println("****************************"+tmptaxonbase);
                         if (!isSynonym) {
-                            classification.addChildTaxon((Taxon)tmptaxonbase, refMods, null);
+                            classification.addChildTaxon((Taxon)tmpTaxonBase, refMods, null);
                         }
                     } else{
-                        hierarchy = new HashMap<Rank, Taxon>();
-                        //System.out.println("LOOK FOR PARENT "+taxonnamebase.toString()+", "+tmptaxonbase.toString());
+                        hierarchy = new HashMap<>();
+                        //System.out.println("LOOK FOR PARENT "+taxonname.toString()+", "+tmptaxonbase.toString());
                         if (!isSynonym){
-                            lookForParentNode(taxonnamebase,(Taxon)tmptaxonbase, refMods,this);
+                            lookForParentNode(taxonName,(Taxon)tmpTaxonBase, refMods,this);
                             //System.out.println("HIERARCHY "+hierarchy);
                             Taxon parent = buildHierarchy();
-                            if(!taxonExistsInClassification(parent,(Taxon)tmptaxonbase)){
+                            if(!taxonExistsInClassification(parent,(Taxon)tmpTaxonBase)){
                                 if(parent !=null) {
-                                    classification.addParentChild(parent, (Taxon)tmptaxonbase, refMods, null);
+                                    classification.addParentChild(parent, (Taxon)tmpTaxonBase, refMods, null);
                                 } else {
-                                    classification.addChildTaxon((Taxon)tmptaxonbase, refMods, null);
+                                    classification.addChildTaxon((Taxon)tmpTaxonBase, refMods, null);
                                 }
                                 importer.getClassificationService().saveOrUpdate(classification);
                             }
@@ -3806,59 +3686,93 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     }
                 }
                 importer.getClassificationService().saveOrUpdate(classification);
-                //            refreshTransaction();
-                if(isSynonym) {
+                 if(isSynonym) {
                     try{
-                        Synonym castTest=CdmBase.deproxy(tmptaxonbase, Synonym.class);
+                        Synonym castTest=CdmBase.deproxy(tmpTaxonBase, Synonym.class);
                     }catch(Exception e){
-                        TaxonNameBase<?,?> existingTnb = tmptaxonbase.getName();
-                        Synonym castTest = new Synonym(existingTnb, refMods);
+                        TaxonName existingTnb = tmpTaxonBase.getName();
+                        Synonym castTest = Synonym.NewInstance(existingTnb, refMods);
                         importer.getTaxonService().saveOrUpdate(castTest);
-                        tmptaxonbase=CdmBase.deproxy(castTest, Synonym.class);
+                        tmpTaxonBase=CdmBase.deproxy(castTest, Synonym.class);
                     }
                 }
             }
             if(!isSynonym) {
-                taxon=CdmBase.deproxy(tmptaxonbase, Taxon.class);
+                taxon=CdmBase.deproxy(tmpTaxonBase, Taxon.class);
             } else {
-                syno=CdmBase.deproxy(tmptaxonbase, Synonym.class);
-            }
-
-
-
-        }
-
-
-        /**
+                syno=CdmBase.deproxy(tmpTaxonBase, Synonym.class);
+            }
+
+        }
+
+               private boolean checkNodeNameReplaceable(Taxon nodeTaxon, TaxonBase<?> newTaxon) {
+                       //TODO preliminary check
+                       if (newTaxon.isInstanceOf(Synonym.class)){
+                               return false;
+                       }
+                       INonViralName nodeName = nodeTaxon.getName();
+                       INonViralName newName = newTaxon.getName();
+                       if (nodeTaxon.getName() == null ||  newName == null){
+                               return false;
+                       }
+                       if (nodeTaxon.getDescriptions().size() > 0 || nodeName.getDescriptions().size() > 0 || nodeName.getTypeDesignations().size() > 0 ){
+                               return false;
+                       }
+                       boolean compare = true;
+                       for (NomenclaturalStatus status : newName.getStatus() ){
+                               compare &= compareStatus(nodeTaxon, status.getType());
+                       }
+                       if (! compare){
+                               return false;
+                       }
+
+                       if (nodeName.getNameCache() != null && nodeName.getNameCache().equals(newName.getNameCache())){
+                               if (nodeName.getNameCache().equals(nodeName.getTitleCache())){
+                                       if (newName.getNameCache().length() < newName.getTitleCache().length()){
+                                               logger.warn("We still need to check, if node was automatically created via hierarchy creation: " + nodeName.getNameCache());
+                                               return true;
+                                       }
+                               }
+                       }
+
+                       return false;
+               }
+
+               /**
          *
          */
         private Taxon buildHierarchy() {
             logger.info("buildHierarchy");
             Taxon higherTaxon = null;
             //add the maxRank as a root
-            if(hierarchy.containsKey(configState.getConfig().getMaxRank())){
-                Taxon ct=hierarchy.get(configState.getConfig().getMaxRank());
+            if(hierarchy.containsKey(state2.getConfig().getMaxRank())){
+                Taxon ct=hierarchy.get(state2.getConfig().getMaxRank());
                 if(!taxonExistsInClassification(higherTaxon, ct)) {
-                    //System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"+hierarchy.get(configState.getConfig().getMaxRank()));
-                    classification.addChildTaxon(ct, refMods, null);
+                   classification.addChildTaxon(ct, refMods, null);
                 }
-                higherTaxon = hierarchy.get(configState.getConfig().getMaxRank());
+                higherTaxon = hierarchy.get(state2.getConfig().getMaxRank());
                 //                return higherTaxon;
             }
             //add the relation to the highertaxon, except if the current rank to add IS the maxRank
-            if(hierarchy.containsKey(Rank.SUBFAMILY()) && !configState.getConfig().getMaxRank().equals(Rank.SUBFAMILY())){
+
+            //TODO higher Ranks
+
+            if(hierarchy.containsKey(Rank.FAMILY()) && !state2.getConfig().getMaxRank().equals(Rank.FAMILY())){
+                higherTaxon=saveAndGetHigherTaxon(Rank.FAMILY(),higherTaxon);
+            }
+            if(hierarchy.containsKey(Rank.SUBFAMILY()) && !state2.getConfig().getMaxRank().equals(Rank.SUBFAMILY())){
                 higherTaxon=saveAndGetHigherTaxon(Rank.SUBFAMILY(),higherTaxon);
             }
-            if(hierarchy.containsKey(Rank.TRIBE())&& !configState.getConfig().getMaxRank().equals(Rank.TRIBE())){
+            if(hierarchy.containsKey(Rank.TRIBE())&& !state2.getConfig().getMaxRank().equals(Rank.TRIBE())){
                 higherTaxon=saveAndGetHigherTaxon(Rank.TRIBE(),higherTaxon);
             }
-            if(hierarchy.containsKey(Rank.SUBTRIBE())&& !configState.getConfig().getMaxRank().equals(Rank.SUBTRIBE())){
+            if(hierarchy.containsKey(Rank.SUBTRIBE())&& !state2.getConfig().getMaxRank().equals(Rank.SUBTRIBE())){
                 higherTaxon=saveAndGetHigherTaxon(Rank.SUBTRIBE(),higherTaxon);
             }
-            if(hierarchy.containsKey(Rank.GENUS())&& !configState.getConfig().getMaxRank().equals(Rank.SUBGENUS())){
+            if(hierarchy.containsKey(Rank.GENUS())&& !state2.getConfig().getMaxRank().equals(Rank.SUBGENUS())){
                 higherTaxon=saveAndGetHigherTaxon(Rank.GENUS(),higherTaxon);
             }
-            if(hierarchy.containsKey(Rank.SUBGENUS())&& !configState.getConfig().getMaxRank().equals(Rank.SUBGENUS())){
+            if(hierarchy.containsKey(Rank.SUBGENUS())&& !state2.getConfig().getMaxRank().equals(Rank.SUBGENUS())){
                 higherTaxon=saveAndGetHigherTaxon(Rank.SUBGENUS(),higherTaxon);
             }
             importer.getClassificationService().saveOrUpdate(classification);
@@ -3873,7 +3787,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 } else
                     if(higherTaxon == null && ct !=null) {
                         classification.addChildTaxon(ct, refMods, null);
-                    }
+                }
             }
             return ct;
         }
@@ -3908,9 +3822,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         /**
          * @param nameToBeFilledTest
          */
-        @SuppressWarnings("rawtypes")
-        public void setParsedName(TaxonNameBase nameToBeFilledTest) {
-            this.taxonnamebase = (NonViralName<?>) nameToBeFilledTest;
+        public void setParsedName(TaxonName nameToBeFilledTest) {
+            this.taxonName = TaxonName.castAndDeproxy(nameToBeFilledTest);
 
         }
         //variety dwcranks:varietyEpithet
@@ -3929,8 +3842,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         /**
          * @return
          */
-        public NonViralName<?> getTaxonNameBase() {
-            return taxonnamebase;
+        public TaxonName getTaxonName() {
+            return taxonName;
         }
 
         /**
@@ -3971,10 +3884,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
             List<TaxonBase> tmpListFiltered = new ArrayList<TaxonBase>();
 
-            Pager<TaxonBase> taxontest = importer.getTaxonService().findByTitle(TaxonBase.class, fullname, MatchMode.BEGINNING, null, null, null, null, null);
+            Pager<TaxonBase> taxontest = importer.getTaxonService().findByTitleWithRestrictions(TaxonBase.class, fullname, MatchMode.BEGINNING, null, null, null, null, null);
 
             tmpListFiltered.addAll(taxontest.getRecords());
-            taxontest = importer.getTaxonService().findByTitle(TaxonBase.class, partialname, MatchMode.BEGINNING, null, null, null, null, null);
+            taxontest = importer.getTaxonService().findByTitleWithRestrictions(TaxonBase.class, partialname, MatchMode.BEGINNING, null, null, null, null, null);
             tmpListFiltered.addAll(taxontest.getRecords());
 
             //logger.info("tmpListFiltered returned: "+tmpListFiltered.size());
@@ -3986,15 +3899,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
             boolean foundIdentic=false;
             Taxon tmp=null;
-            //            Taxon tmpPartial=null;
             for (TaxonBase tmpb:tmpListFiltered){
                 if(tmpb !=null){
-                    TaxonNameBase tnb =  tmpb.getName();
+                    TaxonName tnb =  tmpb.getName();
                     Rank crank=null;
                     if (tnb != null){
-                        //                        //System.out.println(tnb.getTitleCache());
-                        //                        if (tnb.getTitleCache().split("sec.")[0].equals(partialname) ||tnb.getTitleCache().split("sec.")[0].equals(fullname) ){
-                        if(globalrank.equals(rank) || (globalrank.isLower(Rank.SPECIES()) && rank.equals(Rank.SPECIES()))){
+                         if(globalrank.equals(rank) || (globalrank.isLower(Rank.SPECIES()) && rank.equals(Rank.SPECIES()))){
                             if (tnb.getTitleCache().split("sec.")[0].trim().equalsIgnoreCase(fullname) ){
                                 crank =tnb.getRank();
                                 if (crank !=null && rank !=null){
@@ -4059,13 +3969,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             }
             if ((tmp == null || !foundIdentic) ||  (tmp != null && !statusMatch) ||  (tmp != null && !appendedMatch && !statusMatch)){
 
-                NonViralName<?> tnb = getNonViralNameAccNomenclature();
+                INonViralName tnb = getNonViralNameAccNomenclature();
                 tnb.setRank(rank);
 
                 if(statusType != null) {
                     tnb.addStatus(NomenclaturalStatus.NewInstance(statusType));
                 }
-                if(getStatus()!=null) {
+                if(StringUtils.isNotBlank(getStatus())) {
                     tnb.setAppendedPhrase(getStatus());
                 }
 
@@ -4082,10 +3992,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 }
 
                 if (rank.equals(globalrank) && author != null) {
-                    if(fullname.indexOf("opulifolium")>-1) {
-                        //System.out.println("AUTOR: "+author);
-                    }
-                    tnb.setCombinationAuthorTeam(findOrCreateAuthor(author));
+
+                    tnb.setCombinationAuthorship(findOrCreateAuthor(author));
                     if (getIdentifier() !=null && !getIdentifier().isEmpty()){
                         Taxon taxonLSID = getTaxonByLSID(getIdentifier());
                         if (taxonLSID !=null) {
@@ -4129,9 +4037,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     if (rank.equals(Rank.FORM())) {
                         tmp = buildForm(fullname, partialname, tnb);
                     }
+                    if (tmp != null){
+                       TaxonXTreatmentExtractor.this.sourceHandler.addSource(refMods, tmp);
+                    }
 
                     importer.getClassificationService().saveOrUpdate(classification);
                 }
+
             }
 
             tmp = CdmBase.deproxy(tmp, Taxon.class);
@@ -4142,24 +4054,24 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     tmp = CdmBase.deproxy(tmp, Taxon.class);
                 }
             }
-            TaxonNameBase tnb = CdmBase.deproxy(tmp.getName(), TaxonNameBase.class);
 
             this.taxon=tmp;
-            castTaxonNameBase(tnb, taxonnamebase);
+
             return tmp;
         }
+
         /**
          * @param tnb
          * @return
          */
-        private Taxon buildSubfamily(NonViralName<?> tnb) {
+        private Taxon buildSubfamily(INonViralName tnb) {
             Taxon tmp;
             //            tnb.generateTitle();
             tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //                sourceHandler.addSource(refMods, tmp);
@@ -4178,14 +4090,14 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildFamily(NonViralName<?> tnb) {
+        private Taxon buildFamily(INonViralName tnb) {
             Taxon tmp;
             //            tnb.generateTitle();
             tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4199,8 +4111,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildForm(String fullname, String partialname, NonViralName<?> tnb) {
-            Taxon tmp;
+        private Taxon buildForm(String fullname, String partialname, INonViralName tnb) {
             if (genusName !=null) {
                 tnb.setGenusOrUninomial(genusName.getGenusOrUninomial());
             }
@@ -4216,14 +4127,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             if(partialname!= null) {
                 tnb.setInfraSpecificEpithet(partialname);
             }
-            tnb.generateTitle();
-            //TODO how to save form??
+             //TODO how to save form??
             tnb.setTitleCache(fullname, true);
-            tmp = findMatchingTaxon(tnb,refMods);
+            Taxon tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4250,7 +4160,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildVariety(String fullname, String partialname, NonViralName<?> tnb) {
+        private Taxon buildVariety(String fullname, String partialname, INonViralName tnb) {
             Taxon tmp;
             if (genusName !=null) {
                 tnb.setGenusOrUninomial(genusName.getGenusOrUninomial());
@@ -4272,8 +4182,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4300,8 +4210,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildSubspecies(String partialname, NonViralName<?> tnb) {
-            Taxon tmp;
+        private Taxon buildSubspecies(String partialname, INonViralName tnb) {
             if (genusName !=null) {
                 tnb.setGenusOrUninomial(genusName.getGenusOrUninomial());
             }
@@ -4314,13 +4223,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 tnb.setSpecificEpithet(speciesName.getSpecificEpithet());
             }
             tnb.setInfraSpecificEpithet(partialname);
-            tnb.generateTitle();
-            tmp = findMatchingTaxon(tnb,refMods);
+            Taxon tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum())
+                if(!state2.getConfig().doKeepOriginalSecundum())
                  {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                    tmp.setSec(state2.getConfig().getSecundum());
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
                 }
@@ -4342,8 +4250,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildSpecies(String partialname, NonViralName<?> tnb) {
-            Taxon tmp;
+        private Taxon buildSpecies(String partialname, INonViralName tnb) {
             if (genusName !=null) {
                 tnb.setGenusOrUninomial(genusName.getGenusOrUninomial());
             }
@@ -4351,12 +4258,11 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 tnb.setInfraGenericEpithet(subgenusName.getInfraGenericEpithet());
             }
             tnb.setSpecificEpithet(partialname.toLowerCase());
-            tnb.generateTitle();
-            tmp = findMatchingTaxon(tnb,refMods);
+            Taxon tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4383,18 +4289,16 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildSubgenus(String partialname, NonViralName<?> tnb) {
-            Taxon tmp;
+        private Taxon buildSubgenus(String partialname, INonViralName tnb) {
             tnb.setInfraGenericEpithet(partialname);
             if (genusName !=null) {
                 tnb.setGenusOrUninomial(genusName.getGenusOrUninomial());
             }
-            tnb.generateTitle();
-            tmp = findMatchingTaxon(tnb,refMods);
+            Taxon tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4414,17 +4318,17 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildGenus(String partialname, NonViralName<?> tnb) {
+        private Taxon buildGenus(String partialname, INonViralName tnb) {
             Taxon tmp;
             tnb.setGenusOrUninomial(partialname);
-            tnb.generateTitle();
+
 
             tmp = findMatchingTaxon(tnb,refMods);
             if(tmp ==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum())
+                if(!state2.getConfig().doKeepOriginalSecundum())
                  {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                    tmp.setSec(state2.getConfig().getSecundum());
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
                 }
@@ -4463,14 +4367,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildSubtribe(NonViralName<?> tnb) {
-            Taxon tmp;
-            tnb.generateTitle();
-            tmp = findMatchingTaxon(tnb,refMods);
+        private Taxon buildSubtribe(INonViralName tnb) {
+            Taxon tmp = findMatchingTaxon(tnb,refMods);
             if(tmp==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4489,14 +4391,12 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param tnb
          * @return
          */
-        private Taxon buildTribe(NonViralName<?> tnb) {
-            Taxon tmp;
-            tnb.generateTitle();
-            tmp = findMatchingTaxon(tnb,refMods);
+        private Taxon buildTribe(INonViralName tnb) {
+            Taxon tmp = findMatchingTaxon(tnb,refMods);
             if(tmp==null){
                 tmp = Taxon.NewInstance(tnb, sourceUrlRef);
-                if(!configState.getConfig().doKeepOriginalSecundum()) {
-                    tmp.setSec(configState.getConfig().getSecundum());
+                if(!state2.getConfig().doKeepOriginalSecundum()) {
+                    tmp.setSec(state2.getConfig().getSecundum());
                 }
                 //                tmp.setSec(refMods);
                 //sourceHandler.addSource(refMods, tmp);
@@ -4546,7 +4446,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     if (currentlsid !=null){
                         if (currentlsid.getLsid().equals(lsid.getLsid())){
                             try{
-                                return (Taxon) t;
+                                return t;
                             }
                             catch(Exception e){logger.warn("Exception occurred while comparing LSIDs "+e );}
                         }
@@ -4688,8 +4588,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         @SuppressWarnings("rawtypes")
         public void setFamily(Taxon family) {
             this.family = family;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(family.getName(), TaxonNameBase.class);
-            familyName = castTaxonNameBase(taxonNameBase,familyName);
+            familyName = CdmBase.deproxy(family.getName());
         }
         /**
          * @return the subfamily
@@ -4703,8 +4602,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         @SuppressWarnings("rawtypes")
         public void setSubfamily(Taxon subfamily) {
             this.subfamily = subfamily;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(subfamily.getName(), TaxonNameBase.class);
-            subfamilyName = castTaxonNameBase(taxonNameBase,subfamilyName);
+            subfamilyName = CdmBase.deproxy(subfamily.getName());
         }
         /**
          * @return the tribe
@@ -4718,8 +4616,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         @SuppressWarnings("rawtypes")
         public void setTribe(Taxon tribe) {
             this.tribe = tribe;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(tribe.getName(), TaxonNameBase.class);
-            tribeName = castTaxonNameBase(taxonNameBase,tribeName);
+            tribeName = CdmBase.deproxy(tribe.getName());
         }
         /**
          * @return the subtribe
@@ -4733,8 +4630,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         @SuppressWarnings("rawtypes")
         public void setSubtribe(Taxon subtribe) {
             this.subtribe = subtribe;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(subtribe.getName(), TaxonNameBase.class);
-            subtribeName =castTaxonNameBase(taxonNameBase,subtribeName);
+            subtribeName =CdmBase.deproxy(subtribe.getName());
         }
         /**
          * @return the genus
@@ -4747,10 +4643,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          */
         @SuppressWarnings("rawtypes")
         public void setGenus(Taxon genus) {
-            this.genus = genus;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(genus.getName(), TaxonNameBase.class);
-            genusName = castTaxonNameBase(taxonNameBase,genusName);
-            //System.out.println("GENUSNAME: "+genusName.toString());
+            if (genus != null){
+                       this.genus = genus;
+                   genusName = CdmBase.deproxy(genus.getName());
+            }
         }
         /**
          * @return the subgenus
@@ -4764,8 +4660,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         @SuppressWarnings("rawtypes")
         public void setSubgenus(Taxon subgenus) {
             this.subgenus = subgenus;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(subgenus.getName(), TaxonNameBase.class);
-            subgenusName = castTaxonNameBase(taxonNameBase,subgenusName);
+            subgenusName = CdmBase.deproxy(subgenus.getName());
         }
         /**
          * @return the species
@@ -4777,11 +4672,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
          * @param species the species to set
          */
         public void setSpecies(Taxon species) {
-            this.species = species;
-            @SuppressWarnings("rawtypes")
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(species.getName(), TaxonNameBase.class);
-            speciesName = castTaxonNameBase(taxonNameBase,speciesName);
-
+               if (species != null){
+                   this.species = species;
+                   speciesName = CdmBase.deproxy(species.getName());
+               }
         }
         /**
          * @return the subspecies
@@ -4795,8 +4689,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         @SuppressWarnings("rawtypes")
         public void setSubspecies(Taxon subspecies) {
             this.subspecies = subspecies;
-            TaxonNameBase taxonNameBase = CdmBase.deproxy(subspecies.getName(), TaxonNameBase.class);
-            subspeciesName = castTaxonNameBase(taxonNameBase,subspeciesName);
+            subspeciesName = CdmBase.deproxy(subspecies.getName());
 
         }
 
@@ -4810,7 +4703,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
     private void addProblematicStatusToFile(String status) {
         try{
-            FileWriter fstream = new FileWriter("/home/pkelbert/Bureau/StatusUnknown_"+classification.getTitleCache()+".txt",true);
+            FileWriter fstream = new FileWriter(TaxonXImport.LOG_FOLDER + "StatusUnknown_"+classification.getTitleCache()+".txt",true);
             BufferedWriter out = new BufferedWriter(fstream);
             out.write(status+"\n");
             //Close the output stream
@@ -4827,15 +4720,15 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param tnb
      * @return
      */
-    private Taxon findMatchingTaxon(NonViralName<?> tnb, Reference refMods) {
+    private Taxon findMatchingTaxon(INonViralName tnb, Reference refMods) {
         logger.info("findMatchingTaxon");
         Taxon tmp=null;
 
         refMods=CdmBase.deproxy(refMods, Reference.class);
         boolean insertAsExisting =false;
-        List<Taxon> existingTaxons = new ArrayList<Taxon>();
+        List<Taxon> existingTaxa = new ArrayList<Taxon>();
         try {
-            existingTaxons = getMatchingTaxon(tnb);
+            existingTaxa = getMatchingTaxa(TaxonName.castAndDeproxy(tnb));
         } catch (Exception e1) {
             // TODO Auto-generated catch block
             e1.printStackTrace();
@@ -4846,8 +4739,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         String author2="";
         String t1="";
         String t2="";
-        for (Taxon bestMatchingTaxon:existingTaxons){
-            if (!existingTaxons.isEmpty() && configState.getConfig().isInteractWithUser() && !insertAsExisting) {
+        for (Taxon bestMatchingTaxon : existingTaxa){
+            if (!existingTaxa.isEmpty() && state2.getConfig().isInteractWithUser() && !insertAsExisting) {
                 //                System.out.println("tnb "+tnb.getTitleCache());
                 //                System.out.println("ext "+bestMatchingTaxon.getTitleCache());
                 try {
@@ -4859,8 +4752,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                     e.printStackTrace();
                 }
                 try {
-                    if(castTaxonNameBase(bestMatchingTaxon.getName()).getAuthorshipCache()!=null) {
-                        author2=castTaxonNameBase(bestMatchingTaxon.getName()).getAuthorshipCache();
+                    if(bestMatchingTaxon.getName().getAuthorshipCache()!=null) {
+                        author2=bestMatchingTaxon.getName().getAuthorshipCache();
                     }
                 } catch (Exception e) {
                     // TODO Auto-generated catch block
@@ -4909,7 +4802,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param similarityAuthor
      * @return
      */
-    private boolean compareAndCheckTaxon(NonViralName<?> tnb, Reference<?> refMods, double similarityScore,
+    private boolean compareAndCheckTaxon(INonViralName tnb, Reference refMods, double similarityScore,
             Taxon bestMatchingTaxon, double similarityAuthor) {
         //logger.info("compareAndCheckTaxon");
         boolean insertAsExisting;
@@ -4925,7 +4818,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         }
         //        }
 
-        logDecision(tnb,bestMatchingTaxon,insertAsExisting, refMods);
+        logDecision(tnb, bestMatchingTaxon, insertAsExisting, refMods);
         return insertAsExisting;
     }
 
@@ -4933,9 +4826,13 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @return
      */
     @SuppressWarnings("rawtypes")
-    private List<Taxon> getMatchingTaxon(TaxonNameBase tnb) {
+    private List<Taxon> getMatchingTaxa(TaxonName tnb) {
         //logger.info("getMatchingTaxon");
-        Pager<TaxonBase> pager=importer.getTaxonService().findByTitle(TaxonBase.class, tnb.getTitleCache().split("sec.")[0].trim(), MatchMode.BEGINNING, null, null, null, null, null);
+       if (tnb.getTitleCache() == null){
+               tnb.setTitleCache(tnb.toString(), tnb.isProtectedTitleCache());
+       }
+
+        Pager<TaxonBase> pager=importer.getTaxonService().findByTitleWithRestrictions(TaxonBase.class, tnb.getTitleCache().split("sec.")[0].trim(), MatchMode.BEGINNING, null, null, null, null, null);
         List<TaxonBase>records = pager.getRecords();
 
         List<Taxon> existingTaxons = new ArrayList<Taxon>();
@@ -5031,42 +4928,42 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         return costs[s2.length()];
     }
 
-    Map<Rank, Taxon> hierarchy = new HashMap<Rank, Taxon>();
+    Map<Rank, Taxon> hierarchy = new HashMap<>();
     /**
-     * @param taxonnamebase
+     * @param taxonName
      */
     @SuppressWarnings("rawtypes")
-    public void lookForParentNode(NonViralName<?> taxonnamebase, Taxon tax, Reference<?> ref, MyName myName) {
-        logger.info("lookForParentNode "+taxonnamebase.getTitleCache()+" for "+myName.toString());
-        //System.out.println("LOOK FOR PARENT NODE "+taxonnamebase.toString()+"; "+tax.toString()+"; "+taxonnamebase.getRank());
+    public void lookForParentNode(INonViralName taxonName, Taxon tax, Reference ref, MyName myName) {
+        logger.info("lookForParentNode "+taxonName.getTitleCache()+" for "+myName.toString());
+        //System.out.println("LOOK FOR PARENT NODE "+taxonname.toString()+"; "+tax.toString()+"; "+taxonname.getRank());
         INonViralNameParser parser = NonViralNameParserImpl.NewInstance();
-        if (taxonnamebase.getRank().equals(Rank.FORM())){
+        if (taxonName.getRank().equals(Rank.FORM())){
             handleFormHierarchy(ref, myName, parser);
         }
-        if (taxonnamebase.getRank().equals(Rank.VARIETY())){
+        else if (taxonName.getRank().equals(Rank.VARIETY())){
             handleVarietyHierarchy(ref, myName, parser);
         }
-        if (taxonnamebase.getRank().equals(Rank.SUBSPECIES())){
+        else if (taxonName.getRank().equals(Rank.SUBSPECIES())){
             handleSubSpeciesHierarchy(ref, myName, parser);
         }
-        if (taxonnamebase.getRank().equals(Rank.SPECIES())){
+        else if (taxonName.getRank().equals(Rank.SPECIES())){
             handleSpeciesHierarchy(ref, myName, parser);
         }
-        if (taxonnamebase.getRank().equals(Rank.SUBGENUS())){
+        else if (taxonName.getRank().equals(Rank.SUBGENUS())){
             handleSubgenusHierarchy(ref, myName, parser);
         }
 
-        if (taxonnamebase.getRank().equals(Rank.GENUS())){
+        if (taxonName.getRank().equals(Rank.GENUS())){
             handleGenusHierarchy(ref, myName, parser);
         }
-        if (taxonnamebase.getRank().equals(Rank.SUBTRIBE())){
+        if (taxonName.getRank().equals(Rank.SUBTRIBE())){
             handleSubtribeHierarchy(ref, myName, parser);
         }
-        if (taxonnamebase.getRank().equals(Rank.TRIBE())){
+        if (taxonName.getRank().equals(Rank.TRIBE())){
             handleTribeHierarchy(ref, myName, parser);
         }
 
-        if (taxonnamebase.getRank().equals(Rank.SUBFAMILY())){
+        if (taxonName.getRank().equals(Rank.SUBFAMILY())){
             handleSubfamilyHierarchy(ref, myName, parser);
         }
     }
@@ -5076,14 +4973,14 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleSubfamilyHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleSubfamilyHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         System.out.println("handleSubfamilyHierarchy");
         String parentStr = myName.getFamilyStr();
         Rank r = Rank.FAMILY();
         if(parentStr!=null){
 
             Taxon parent = null;
-            Pager<TaxonBase> taxontest = importer.getTaxonService().findByTitle(TaxonBase.class, parentStr, MatchMode.BEGINNING, null, null, null, null, null);
+            Pager<TaxonBase> taxontest = importer.getTaxonService().findByTitleWithRestrictions(TaxonBase.class, parentStr, MatchMode.BEGINNING, null, null, null, null, null);
             for(TaxonBase tb:taxontest.getRecords()){
                 try {
                     if (tb.getName().getRank().equals(r)) {
@@ -5096,7 +4993,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
                 }
             }
             if(parent == null) {
-                NonViralName<?> parentNameName =  (NonViralName<?>) parser.parseFullName(parentStr, nomenclaturalCode, r);
+                INonViralName parentNameName =  parser.parseFullName(parentStr, nomenclaturalCode, r);
                 Taxon tmp = findMatchingTaxon(parentNameName,ref);
                 if(tmp ==null)
                 {
@@ -5118,7 +5015,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleTribeHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleTribeHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getSubfamilyStr();
         Rank r = Rank.SUBFAMILY();
         if (parentStr == null){
@@ -5126,7 +5023,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             r = Rank.FAMILY();
         }
         if(parentStr!=null){
-            NonViralName<?> parentNameName =  (NonViralName<?>) parser.parseFullName(parentStr, nomenclaturalCode, r);
+            INonViralName parentNameName =  parser.parseFullName(parentStr, nomenclaturalCode, r);
             Taxon parent = Taxon.NewInstance(parentNameName, ref); //sec set null
             //                    importer.getTaxonService().save(parent);
             //                    parent = CdmBase.deproxy(parent, Taxon.class);
@@ -5166,7 +5063,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleSubtribeHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleSubtribeHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getTribeStr();
         Rank r = Rank.TRIBE();
         if (parentStr == null){
@@ -5178,7 +5075,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             r = Rank.FAMILY();
         }
         if(parentStr!=null){
-            NonViralName<?> parentNameName =  (NonViralName<?>) parser.parseFullName(parentStr, nomenclaturalCode, r);
+            INonViralName parentNameName =  parser.parseFullName(parentStr, nomenclaturalCode, r);
             Taxon parent = Taxon.NewInstance(parentNameName, ref); //sec set null
             //                    importer.getTaxonService().save(parent);
             //                    parent = CdmBase.deproxy(parent, Taxon.class);
@@ -5219,7 +5116,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleGenusHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleGenusHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getSubtribeStr();
         Rank r = Rank.SUBTRIBE();
         if (parentStr == null){
@@ -5235,17 +5132,17 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             r = Rank.FAMILY();
         }
         if(parentStr!=null){
-            NonViralName<?> parentNameName =  (NonViralName<?>) parser.parseFullName(parentStr, nomenclaturalCode, r);
+            INonViralName parentNameName =  parser.parseFullName(parentStr, nomenclaturalCode, r);
             Taxon parent = Taxon.NewInstance(parentNameName, ref); //sec set null
             //                    importer.getTaxonService().save(parent);
             //                    parent = CdmBase.deproxy(parent, Taxon.class);
 
-            boolean parentDoesNotExists = true;
+            boolean parentDoesNotExist = true;
             for (TaxonNode p : classification.getAllNodes()){
                 if(p.getTaxon().getTitleCache().equalsIgnoreCase(parent.getTitleCache())) {
                     //                        System.out.println(p.getTaxon().getUuid());
                     //                        System.out.println(parent.getUuid());
-                    parentDoesNotExists = false;
+                    parentDoesNotExist = false;
                     parent=CdmBase.deproxy(p.getTaxon(),    Taxon.class);
                     break;
                 }
@@ -5255,10 +5152,10 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             //                    parent = CdmBase.deproxy(parent, Taxon.class);
             //                    lookForParentNode(parentNameName, parent, ref,myName);
             //                }
-            if(parentDoesNotExists) {
+            if(parentDoesNotExist) {
                 Taxon tmp = findMatchingTaxon(parentNameName,ref);
-                if(tmp ==null)
-                {
+                if(tmp ==null){
+
                     parent=Taxon.NewInstance(parentNameName, ref);
                     importer.getTaxonService().save(parent);
                     parent = CdmBase.deproxy(parent, Taxon.class);
@@ -5277,7 +5174,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleSubgenusHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleSubgenusHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getGenusStr();
         Rank r = Rank.GENUS();
 
@@ -5298,7 +5195,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
             r = Rank.FAMILY();
         }
         if(parentStr!=null){
-            NonViralName<?> parentNameName =  (NonViralName<?>) parser.parseFullName(parentStr, nomenclaturalCode, r);
+            INonViralName parentNameName =  parser.parseFullName(parentStr, nomenclaturalCode, r);
             Taxon parent = Taxon.NewInstance(parentNameName, ref); //sec set null
             //                    importer.getTaxonService().save(parent);
             //                    parent = CdmBase.deproxy(parent, Taxon.class);
@@ -5340,7 +5237,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleSpeciesHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleSpeciesHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getSubgenusStr();
         Rank r = Rank.SUBGENUS();
 
@@ -5377,7 +5274,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleSubSpeciesHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleSubSpeciesHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getSpeciesStr();
         Rank r = Rank.SPECIES();
 
@@ -5421,7 +5318,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleFormHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleFormHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getSubspeciesStr();
         Rank r = Rank.SUBSPECIES();
 
@@ -5469,7 +5366,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param myName
      * @param parser
      */
-    private void handleVarietyHierarchy(Reference<?> ref, MyName myName, INonViralNameParser<?> parser) {
+    private void handleVarietyHierarchy(Reference ref, MyName myName, INonViralNameParser<?> parser) {
         String parentStr = myName.getSubspeciesStr();
         Rank r = Rank.SUBSPECIES();
 
@@ -5519,8 +5416,8 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param r
      * @return
      */
-    private Taxon handleParentName(Reference<?> ref, MyName myName, INonViralNameParser<?> parser, String parentStr, Rank r) {
-        NonViralName<?> parentNameName =  (NonViralName<?>) parser.parseFullName(parentStr, nomenclaturalCode, r);
+    private Taxon handleParentName(Reference ref, MyName myName, INonViralNameParser<?> parser, String parentStr, Rank r) {
+        INonViralName parentNameName =  parser.parseFullName(parentStr, nomenclaturalCode, r);
         Taxon parent = Taxon.NewInstance(parentNameName, ref); //sec set null
         //                    importer.getTaxonService().save(parent);
         //                    parent = CdmBase.deproxy(parent, Taxon.class);
@@ -5538,11 +5435,11 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
         if(parentDoesNotExists) {
             Taxon tmp = findMatchingTaxon(parentNameName,ref);
             //                    System.out.println("FOUND PARENT "+tmp.toString()+" for "+parentNameName.toString());
-            if(tmp ==null)
-            {
+            if(tmp ==null){
+
                 parent=Taxon.NewInstance(parentNameName, ref);
                 importer.getTaxonService().save(parent);
-                parent = CdmBase.deproxy(parent, Taxon.class);
+
             } else {
                 parent=tmp;
             }
@@ -5554,7 +5451,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
 
     private void addNameDifferenceToFile(String originalname, String atomisedname){
         try{
-            FileWriter fstream = new FileWriter("/home/pkelbert/Bureau/NamesDifferent_"+classification.getTitleCache()+".txt",true);
+            FileWriter fstream = new FileWriter(TaxonXImport.LOG_FOLDER + "NamesDifferent_"+classification.getTitleCache()+".txt",true);
             BufferedWriter out = new BufferedWriter(fstream);
             out.write(originalname+" (original) versus "+replaceNull(atomisedname)+" (atomised) \n");
             //Close the output stream
@@ -5571,7 +5468,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
     private void addProblemNameToFile(String name, String author, NomenclaturalCode nomenclaturalCode2, Rank rank) {
         try{
-            FileWriter fstream = new FileWriter("/home/pkelbert/Bureau/NameNotParsed.txt",true);
+            FileWriter fstream = new FileWriter(TaxonXImport.LOG_FOLDER + "NameNotParsed.txt",true);
             BufferedWriter out = new BufferedWriter(fstream);
             out.write(name+"\t"+replaceNull(author)+"\t"+replaceNull(nomenclaturalCode2)+"\t"+replaceNull(rank)+"\n");
             //Close the output stream
@@ -5588,11 +5485,11 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      * @param insertAsExisting
      * @param refMods
      */
-    private void logDecision(NonViralName<?> tnb, Taxon bestMatchingTaxon, boolean insertAsExisting, Reference refMods) {
+    private void logDecision(INonViralName tnb, Taxon bestMatchingTaxon, boolean insertAsExisting, Reference refMods) {
         try{
-            FileWriter fstream = new FileWriter("/home/pkelbert/Bureau/Decisions_"+classification.toString()+".txt",true);
+            FileWriter fstream = new FileWriter(TaxonXImport.LOG_FOLDER + "Decisions_"+classification.toString()+".txt", true);
             BufferedWriter out = new BufferedWriter(fstream);
-            out.write(tnb.getTitleCache()+" sec. "+refMods+"\t"+bestMatchingTaxon.getTitleCache()+"\t"+insertAsExisting+"\n");
+            out.write(tnb.getTitleCache() + " sec. " + refMods + "\t" + bestMatchingTaxon.getTitleCache() + "\t" + insertAsExisting + "\n");
             //Close the output stream
             out.close();
         }catch (Exception e){//Catch exception if any
@@ -5619,7 +5516,7 @@ public class TaxonXTreatmentExtractor extends TaxonXExtractor{
      */
     private void addProblemNameToFile(String type, String name, NomenclaturalCode nomenclaturalCode2, Rank rank, String problems) {
         try{
-            FileWriter fstream = new FileWriter("/home/pkelbert/Bureau/NameNotParsed_"+classification.getTitleCache()+".txt",true);
+            FileWriter fstream = new FileWriter(TaxonXImport.LOG_FOLDER + "NameNotParsed_"+classification.getTitleCache()+".txt",true);
             BufferedWriter out = new BufferedWriter(fstream);
             out.write(type+"\t"+name+"\t"+replaceNull(nomenclaturalCode2)+"\t"+replaceNull(rank)+"\t"+problems+"\n");
             //Close the output stream