newest developments in specimen import
authorAndreas Müller <a.mueller@bgbm.org>
Mon, 23 May 2011 16:27:00 +0000 (16:27 +0000)
committerAndreas Müller <a.mueller@bgbm.org>
Mon, 23 May 2011 16:27:00 +0000 (16:27 +0000)
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/specimen/excel/in/SpecimenCdmExcelImport.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/specimen/excel/in/SpecimenCdmExcelImportConfigurator.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/specimen/excel/in/SpecimenCdmExcelImportState.java
cdmlib-io/src/main/java/eu/etaxonomy/cdm/io/specimen/excel/in/SpecimenRow.java

index abfe2d8030fb4cdc5000cdfbcb91e310de919147..03128b31c9f9be7e75fa95f486b4de4c9a496df6 100644 (file)
@@ -21,26 +21,45 @@ import org.springframework.stereotype.Component;
 
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade.DerivedUnitType;
+import eu.etaxonomy.cdm.api.service.config.MatchingTaxonConfigurator;
+import eu.etaxonomy.cdm.api.service.pager.Pager;
 import eu.etaxonomy.cdm.common.CdmUtils;
+import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
 import eu.etaxonomy.cdm.io.common.ICdmIO;
 import eu.etaxonomy.cdm.io.common.mapping.UndefinedTransformerMethodException;
 import eu.etaxonomy.cdm.io.excel.common.ExcelImporterBase;
+import eu.etaxonomy.cdm.io.specimen.excel.in.SpecimenRow.DeterminationLight;
 import eu.etaxonomy.cdm.model.agent.AgentBase;
 import eu.etaxonomy.cdm.model.agent.Person;
 import eu.etaxonomy.cdm.model.agent.Team;
+import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
+import eu.etaxonomy.cdm.model.common.Annotation;
+import eu.etaxonomy.cdm.model.common.AnnotationType;
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
+import eu.etaxonomy.cdm.model.common.Language;
+import eu.etaxonomy.cdm.model.common.TimePeriod;
+import eu.etaxonomy.cdm.model.description.IndividualsAssociation;
+import eu.etaxonomy.cdm.model.description.TaxonDescription;
 import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.location.NamedAreaLevel;
 import eu.etaxonomy.cdm.model.location.NamedAreaType;
 import eu.etaxonomy.cdm.model.location.ReferenceSystem;
 import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;
 import eu.etaxonomy.cdm.model.name.NomenclaturalCode;
+import eu.etaxonomy.cdm.model.name.NonViralName;
+import eu.etaxonomy.cdm.model.name.Rank;
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;
 import eu.etaxonomy.cdm.model.name.TaxonNameBase;
 import eu.etaxonomy.cdm.model.occurrence.Collection;
+import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;
+import eu.etaxonomy.cdm.model.occurrence.DeterminationModifier;
 import eu.etaxonomy.cdm.model.reference.Reference;
 import eu.etaxonomy.cdm.model.reference.ReferenceFactory;
+import eu.etaxonomy.cdm.model.taxon.Taxon;
+import eu.etaxonomy.cdm.model.taxon.TaxonBase;
+import eu.etaxonomy.cdm.persistence.query.MatchMode;
+import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
 import eu.etaxonomy.cdm.strategy.parser.NonViralNameParserImpl;
 
 /**
@@ -89,12 +108,19 @@ public class SpecimenCdmExcelImport  extends ExcelImporterBase<SpecimenCdmExcelI
        private static final String ID_IN_SOURCE_COLUMN = "IdInSource";
        
        
-       private static final String SPECIFIC_EPITHET_COLUMN = "SpecificEpithet";
+       private static final String RANK_COLUMN = "Rank";
+       private static final String FULL_NAME_COLUMN = "FullName";
        private static final String FAMILY_COLUMN = "Family";
        private static final String GENUS_COLUMN = "Genus";
-       private static final String AUTHOR_COLUMN = "Author";
+       private static final String SPECIFIC_EPITHET_COLUMN = "SpecificEpithet";
+       private static final String INFRASPECIFIC_EPITHET_COLUMN = "InfraSpecificEpithet";
+       private static final String DETERMINATION_AUTHOR_COLUMN = "Author";
+       private static final String DETERMINATION_MODIFIER_COLUMN = "DeterminationModifier";
+       private static final String DETERMINED_BY_COLUMN = "DeterminationBy";
+       private static final String DETERMINED_WHEN_COLUMN = "DeterminationWhen";
+       private static final String DETERMINATION_NOTES_COLUMN = "DeterminationNote";
+       
        
-
 
        public SpecimenCdmExcelImport() {
                super();
@@ -132,7 +158,6 @@ public class SpecimenCdmExcelImport  extends ExcelImporterBase<SpecimenCdmExcelI
                        continue;
                }
                
-               
                if (key.equalsIgnoreCase(UUID_COLUMN)) {
                        row.setUuid(UUID.fromString(value)); //VALIDATE UUID
                        } else if(key.equalsIgnoreCase(BASIS_OF_RECORD_COLUMN)) {
@@ -176,14 +201,32 @@ public class SpecimenCdmExcelImport  extends ExcelImporterBase<SpecimenCdmExcelI
                                row.setLocality(value);         
                        } else if(key.equalsIgnoreCase(BARCODE_COLUMN)) {
                                row.setBarcode(value);          
-                       } else if(key.equalsIgnoreCase(AUTHOR_COLUMN)) {
+                       } else if(key.equalsIgnoreCase(DETERMINATION_AUTHOR_COLUMN)) {
                                row.setAuthor(value);           
+                       
                        } else if(key.equalsIgnoreCase(FAMILY_COLUMN)) {
-                               row.setFamily(value);           
+                               row.putDeterminationFamily(index, value);               
                        } else if(key.equalsIgnoreCase(GENUS_COLUMN)) {
-                               row.setGenus(value);            
+                               row.putDeterminationGenus(index, value);                
                        } else if(key.equalsIgnoreCase(SPECIFIC_EPITHET_COLUMN)) {
-                               row.setSpecificEpithet(value);          
+                               row.putDeterminationSpeciesEpi(index, value);                   
+                       } else if(key.equalsIgnoreCase(INFRASPECIFIC_EPITHET_COLUMN)) {
+                               row.putDeterminationInfraSpeciesEpi(index, value);                      
+                       } else if(key.equalsIgnoreCase(RANK_COLUMN)) {
+                               row.putDeterminationRank(index, value);                 
+                       } else if(key.equalsIgnoreCase(FULL_NAME_COLUMN)) {
+                               row.putDeterminationFullName(index, value);                     
+                       } else if(key.equalsIgnoreCase(DETERMINATION_AUTHOR_COLUMN)) {
+                               row.putDeterminationAuthor(index, value);                       
+                       } else if(key.equalsIgnoreCase(DETERMINATION_MODIFIER_COLUMN)) {
+                               row.putDeterminationDeterminationModifier(index, value);                        
+                       } else if(key.equalsIgnoreCase(DETERMINATION_NOTES_COLUMN)) {
+                               row.putDeterminationDeterminationNotes(index, value);                   
+                       } else if(key.equalsIgnoreCase(DETERMINED_BY_COLUMN)) {
+                               row.putDeterminationDeterminedBy(index, value);                 
+                       } else if(key.equalsIgnoreCase(DETERMINED_WHEN_COLUMN)) {
+                               row.putDeterminationDeterminedWhen(index, value);                       
+                       
                        } else if(key.equalsIgnoreCase(COLLECTION_CODE_COLUMN)) {
                                row.setCollectionCode(value);           
                        } else if(key.equalsIgnoreCase(COLLECTION_COLUMN)) {
@@ -245,7 +288,24 @@ public class SpecimenCdmExcelImport  extends ExcelImporterBase<SpecimenCdmExcelI
                for (SpecimenTypeDesignation designation : row.getTypeDesignations()){
                        facade.innerDerivedUnit().addSpecimenTypeDesignation(designation);
                }
-               
+               boolean isFirstDetermination = true;
+               for (DeterminationLight determinationLight : row.getDetermination()){
+                       Taxon taxon = findBestMatchingTaxon(state, determinationLight, true);
+                       TaxonNameBase<?,?> name = findBestMatchingName(state, determinationLight);
+                       if (state.getConfig().isMakeIndividualAssociations()){
+                               IndividualsAssociation indivAssociciation = IndividualsAssociation.NewInstance();
+                               indivAssociciation.setAssociatedSpecimenOrObservation(facade.innerDerivedUnit());
+                               getTaxonDescription(taxon).addElement(indivAssociciation);
+                       }
+                       if (isFirstDetermination && state.getConfig().isFirstDeterminationIsStoredUnder()){
+                               facade.setStoredUnder(name);
+                       }
+                       if (state.getConfig().isDeterminationsAreDeterminationEvent()){
+                               DeterminationEvent detEvent = makeDeterminationEvent(state, determinationLight, taxon);
+                               facade.addDetermination(detEvent);
+                       }
+                       isFirstDetermination = false;
+               }
                
                
                //save
@@ -253,6 +313,142 @@ public class SpecimenCdmExcelImport  extends ExcelImporterBase<SpecimenCdmExcelI
                return true;
        }
 
+       /**
+        * This method tries to find the best matching taxon depending on the import configuration,
+        * the taxon name information and the concept information available.
+        * 
+        * 
+        * @param state
+        * @param determinationLight
+        * @param createIfNotExists
+        * @return
+        */
+       private Taxon findBestMatchingTaxon(SpecimenCdmExcelImportState state, DeterminationLight determinationLight, boolean createIfNotExists) {
+               NonViralName name = makeTaxonName(state, determinationLight);
+               
+               String titleCache = makeSearchNameTitleCache(state, determinationLight, name);
+               
+               
+               
+               if (! StringUtils.isBlank(titleCache)){
+                       MatchingTaxonConfigurator matchConfigurator = MatchingTaxonConfigurator.NewInstance();
+                       matchConfigurator.setTaxonNameTitle(determinationLight.fullName);
+                       Taxon taxon = getTaxonService().findBestMatchingTaxon(matchConfigurator);
+               
+                       if(taxon == null && createIfNotExists){
+                               logger.info("creating new Taxon from TaxonName '" + titleCache+"'");
+                               UUID secUuid = null; //TODO
+                               Reference sec = null;
+                               if (secUuid != null){
+                                       sec = getReferenceService().find(secUuid);
+                               }
+                               taxon = Taxon.NewInstance(name, sec);
+                       }
+                       return taxon;
+               }else {
+                       return null;
+               }
+       }
+
+       /**
+        * @param state
+        * @param determinationLight
+        * @param name
+        * @return
+        */
+       private String makeSearchNameTitleCache(SpecimenCdmExcelImportState state,
+                       DeterminationLight determinationLight, NonViralName name) {
+               String titleCache = determinationLight.fullName;
+               if (! state.isPreferNameCache()){
+                       String computedTitleCache = name.getTitleCache();
+                       if (StringUtils.isBlank(computedTitleCache)){
+                               titleCache = computedTitleCache;
+                       }
+                       
+               }
+               return titleCache;
+       }
+
+       /**
+        * @param state
+        * @param determinationLight
+        * @return
+        */
+       private NonViralName makeTaxonName(SpecimenCdmExcelImportState state,
+                       DeterminationLight determinationLight) {
+               //TODO correct type by config.nc
+               NonViralName name =NonViralName.NewInstance(null);
+               name.setGenusOrUninomial(determinationLight.genus);
+               name.setSpecificEpithet(determinationLight.genus);
+               name.setInfraSpecificEpithet(determinationLight.infraSpeciesEpi);
+               NomenclaturalCode nc = state.getConfig().getNomenclaturalCode();
+               try {
+                       name.setRank(Rank.getRankByNameOrAbbreviation(determinationLight.rank, nc, true));
+               } catch (UnknownCdmTypeException e) {
+                       String message = "Rank not found: %s: ";
+                       message = String.format(message, determinationLight.rank);
+                       logger.warn(message);
+               }
+               if (StringUtils.isBlank(name.getInfraSpecificEpithet()) && StringUtils.isNotBlank(name.getSpecificEpithet() )){
+                       name.setRank(Rank.SPECIES());
+               }
+               if (StringUtils.isBlank(name.getSpecificEpithet()) && StringUtils.isNotBlank(name.getGenusOrUninomial() )){
+                       name.setRank(Rank.SPECIES());
+               }
+               if (StringUtils.isBlank(name.getTitleCache())){
+                       //TODO test
+                       name.setTitleCache(determinationLight.fullName, true);
+               }
+               return name;
+       }
+
+       private TaxonNameBase findBestMatchingName(SpecimenCdmExcelImportState state, DeterminationLight determinationLight) {
+               
+               NonViralName name = makeTaxonName(state, determinationLight);
+               String titleCache = makeSearchNameTitleCache(state, determinationLight, name);
+               
+               //TODO
+               List<TaxonNameBase> matchingNames = getNameService().findByName(null, titleCache, MatchMode.EXACT, null, null, null, null, null).getRecords();
+               if (matchingNames.size() > 0){
+                       return matchingNames.get(0);
+               } else if (matchingNames.size() > 0){
+                       logger.warn("Get best matching taxon name not yet fully implemeted for specimen import");
+                       return matchingNames.get(0);
+               }else{
+                       return null;    
+               }
+               
+       }
+
+       
+       private DeterminationEvent makeDeterminationEvent(SpecimenCdmExcelImportState state, DeterminationLight determination, Taxon taxon) {
+               DeterminationEvent event = DeterminationEvent.NewInstance();
+               //date
+               TimePeriod date = TimePeriod.parseString(determination.determinedWhen);
+               event.setTimeperiod(date);
+               //by
+               //TODO teams also possible?
+               AgentBase<?> agent = Person.NewTitledInstance(determination.author);
+               event.setActor(agent);
+               
+               //TODO
+               if (StringUtils.isNotBlank(determination.modifier)){
+                       logger.warn("DeterminationModifiers not yet implemented for specimen import");
+               }
+//             DeterminationModifier modifier = DeterminationModifier.NewInstance(term, label, labelAbbrev);
+//             determination.modifier;
+               //notes
+               Annotation annotation = Annotation.NewInstance(determination.notes, AnnotationType.EDITORIAL(), Language.DEFAULT());
+               event.addAnnotation(annotation);
+               return event;
+       }
+
+       private TaxonDescription getTaxonDescription(Taxon taxon) {
+               logger.warn("Get taxon description not yet really implemented");
+               TaxonDescription desc = TaxonDescription.NewInstance(taxon);
+               return desc;
+       }
+
        private AgentBase<?> getOrMakeAgent(SpecimenCdmExcelImportState state, List<String> agents) {
                if (agents.size() == 0){
                        return null;
@@ -313,12 +509,12 @@ public class SpecimenCdmExcelImport  extends ExcelImporterBase<SpecimenCdmExcelI
        
 
        private TaxonNameBase<?, ?> getTaxonName(SpecimenCdmExcelImportState state, String name) {
-               TaxonNameBase result = null;
+               TaxonNameBase<?,?> result = null;
                result = state.getName(name);
                if (result != null){
                        return result;
                }
-               List<TaxonNameBase> list = getNameService().findNamesByTitle(name);
+               List<TaxonNameBase<?,?>> list = getNameService().findNamesByTitle(name);
                //TODO better strategy to find best name, e.g. depending on the classification it is used in
                if (! list.isEmpty()){
                        result = list.get(0);
index 3b9e65c95d6418a639bc0bba84947cb9987b0350..b8d021f95e3cd5b293dd0f2f4012811c13f6ecdc 100644 (file)
@@ -40,8 +40,11 @@ public class SpecimenCdmExcelImportConfigurator extends ExcelImportConfiguratorB
        private boolean doAreaLevels = true;\r
        private boolean useCountry;  //if isocountry and country is available, use country instead of isocountry \r
        private PersonParserFormatEnum personParserFormat = PersonParserFormatEnum.POSTFIX;  //\r
-       private boolean useHexagesimalCoordinates;\r
        \r
+       //if true, determinations are imported also as individualAssociations   \r
+       private boolean makeIndividualAssociations = true;\r
+       private boolean firstDeterminationIsStoredUnder = false;\r
+       private boolean determinationsAreDeterminationEvent = true;\r
        \r
        \r
        @SuppressWarnings("unchecked")\r
@@ -156,6 +159,37 @@ public class SpecimenCdmExcelImportConfigurator extends ExcelImportConfiguratorB
        public boolean isDoAreaLevels() {\r
                return doAreaLevels;\r
        }\r
+\r
+       public void setMakeIndividualAssociations(boolean makeIndividualAssociations) {\r
+               this.makeIndividualAssociations = makeIndividualAssociations;\r
+       }\r
+\r
+       public boolean isMakeIndividualAssociations() {\r
+               return makeIndividualAssociations;\r
+       }\r
+\r
+       public boolean isFirstDeterminationIsStoredUnder() {\r
+               return firstDeterminationIsStoredUnder ;\r
+       }\r
+\r
+       /**\r
+        * @param firstDeterminationIsStoredUnder the firstDeterminationIsStoredUnder to set\r
+        */\r
+       public void setFirstDeterminationIsStoredUnder(boolean firstDeterminationIsStoredUnder) {\r
+               this.firstDeterminationIsStoredUnder = firstDeterminationIsStoredUnder;\r
+       }\r
+       \r
+       public boolean isDeterminationsAreDeterminationEvent() {\r
+               return determinationsAreDeterminationEvent ;\r
+       }\r
+\r
+       /**\r
+        * @param determinationsAreDeterminationEvent the determinationsAreDeterminationEvent to set\r
+        */\r
+       public void setDeterminationsAreDeterminationEvent(     boolean determinationsAreDeterminationEvent) {\r
+               this.determinationsAreDeterminationEvent = determinationsAreDeterminationEvent;\r
+       }\r
+\r
        \r
        \r
        \r
index 6dbb6ed4b43b1dcb7220ca5fa06ddadc49d2e273..4c6e8fb83d4762f93fa893caed514b312533f589 100644 (file)
@@ -32,6 +32,7 @@ public class SpecimenCdmExcelImportState extends ExcelImportState<SpecimenCdmExc
        private static final Logger logger = Logger.getLogger(SpecimenCdmExcelImportState.class);\r
 \r
        private SpecimenRow specimenRow;\r
+       private boolean preferNameCache = true;\r
 \r
        private Map<String, Reference<?>> references = new HashMap<String, Reference<?>>();\r
        private Map<String, Collection> collections = new HashMap<String, Collection>();\r
@@ -91,6 +92,17 @@ public class SpecimenCdmExcelImportState extends ExcelImportState<SpecimenCdmExc
        public TaxonNameBase putName(String key, TaxonNameBase value){\r
                return this.names.put(key, value);\r
        }\r
+\r
+       public boolean isPreferNameCache() {\r
+               return this.preferNameCache;\r
+       }\r
+\r
+       /**\r
+        * @param preferNameCache the preferNameCache to set\r
+        */\r
+       public void setPreferNameCache(boolean preferNameCache) {\r
+               this.preferNameCache = preferNameCache;\r
+       }\r
        \r
 \r
 \r
index 985bbeb308b750fc41efec4df79f12e635bcbbcd..dbea60ff5b51c710de4ca18c595cdd9912a543b6 100644 (file)
@@ -17,9 +17,13 @@ import java.util.UUID;
 import org.apache.log4j.Logger;\r
 \r
 import eu.etaxonomy.cdm.model.common.IdentifiableSource;\r
+import eu.etaxonomy.cdm.model.name.NomenclaturalCode;\r
+import eu.etaxonomy.cdm.model.name.NonViralName;\r
+import eu.etaxonomy.cdm.model.name.Rank;\r
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;\r
 import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignationStatus;\r
 import eu.etaxonomy.cdm.model.name.TaxonNameBase;\r
+import eu.etaxonomy.cdm.model.occurrence.DeterminationEvent;\r
 import eu.etaxonomy.cdm.model.reference.Reference;\r
 \r
 /**\r
@@ -44,9 +48,9 @@ public class SpecimenRow {
        private String barcode;\r
        private String author;\r
        private String absoluteElevation;\r
-       private String family;\r
-       private String genus;\r
-       private String specificEpithet;\r
+//     private String family;\r
+//     private String genus;\r
+//     private String specificEpithet;\r
        private String sex;\r
        private String ecology;\r
        private String plantDescription;\r
@@ -62,17 +66,31 @@ public class SpecimenRow {
        private TreeMap<Integer, IdentifiableSource> sources = new TreeMap<Integer, IdentifiableSource>();\r
        private TreeMap<Integer, String> collectors = new TreeMap<Integer, String>();\r
        private TreeMap<Integer, SpecimenTypeDesignation> types = new TreeMap<Integer, SpecimenTypeDesignation>();\r
-       \r
-       \r
+       private TreeMap<Integer, DeterminationLight> determinations = new TreeMap<Integer, DeterminationLight>();\r
+\r
        \r
 \r
        \r
        public SpecimenRow() {\r
-\r
-//             commonNames = new HashMap<String, List<String>>();\r
        }\r
 \r
        \r
+       //      may be public if necessary\r
+       protected class DeterminationLight{\r
+               String family;\r
+               String genus;\r
+               String rank;\r
+               String fullName;\r
+               String speciesEpi;\r
+               String infraSpeciesEpi;\r
+               String author;\r
+               String modifier;\r
+               String determinedBy;\r
+               String determinedWhen;\r
+               String notes;\r
+       }\r
+       \r
+       \r
 // **************************** GETTER / SETTER *********************************/     \r
        \r
 \r
@@ -192,53 +210,6 @@ public class SpecimenRow {
        }\r
 \r
 \r
-       /**\r
-        * @return the family\r
-        */\r
-       public String getFamily() {\r
-               return family;\r
-       }\r
-\r
-\r
-       /**\r
-        * @param family the family to set\r
-        */\r
-       public void setFamily(String family) {\r
-               this.family = family;\r
-       }\r
-\r
-\r
-       /**\r
-        * @return the genus\r
-        */\r
-       public String getGenus() {\r
-               return genus;\r
-       }\r
-\r
-\r
-       /**\r
-        * @param genus the genus to set\r
-        */\r
-       public void setGenus(String genus) {\r
-               this.genus = genus;\r
-       }\r
-\r
-\r
-       /**\r
-        * @return the specificEpithet\r
-        */\r
-       public String getSpecificEpithet() {\r
-               return specificEpithet;\r
-       }\r
-\r
-\r
-       /**\r
-        * @param specificEpithet the specificEpithet to set\r
-        */\r
-       public void setSpecificEpithet(String specificEpithet) {\r
-               this.specificEpithet = specificEpithet;\r
-       }\r
-\r
 \r
        /**\r
         * @return the ecology\r
@@ -438,7 +409,77 @@ public class SpecimenRow {
                return designation;\r
        }\r
        \r
+       public void putDeterminationFamily(int key, String family){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.family = family;\r
+       }\r
+\r
+       public void putDeterminationFullName(int key, String fullName){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.fullName = fullName;\r
+       }\r
+\r
+       public void putDeterminationRank(int key, String rank){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.rank = rank;\r
+       }\r
+\r
+       public void putDeterminationGenus(int key, String genus){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.genus = genus;\r
+       }\r
+       \r
+       public void putDeterminationSpeciesEpi(int key, String speciesEpi){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.speciesEpi = speciesEpi;\r
+       }\r
+\r
+       public void putDeterminationInfraSpeciesEpi(int key, String infraSpeciesEpi){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.infraSpeciesEpi = infraSpeciesEpi;\r
+       }\r
+\r
+       public void putDeterminationAuthor(int key, String author){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.author = author;\r
+       }\r
+\r
+       public void putDeterminationDeterminedBy(int key, String determinedBy){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.determinedBy = determinedBy;\r
+       }\r
+\r
+       public void putDeterminationDeterminedWhen(int key, String determinedWhen){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.determinedWhen = determinedWhen;\r
+       }\r
+\r
+       public void putDeterminationDeterminationNotes(int key, String notes){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.notes = notes;\r
+       }\r
+       \r
+       public void putDeterminationDeterminationModifier(int key, String modifier){\r
+               DeterminationLight determinationEvent = getOrMakeDetermination(key);\r
+               determinationEvent.modifier = modifier;\r
+       }\r
+       \r
+       public List<DeterminationLight> getDetermination() {\r
+               return getOrdered(determinations);\r
+       }\r
+       \r
+       \r
        \r
+       private DeterminationLight getOrMakeDetermination(int key) {\r
+               DeterminationLight determination = this.determinations.get(key);\r
+               if (determination == null){\r
+                       determination = new DeterminationLight();\r
+                       this.determinations.put(key, determination);\r
+               }\r
+               return determination;\r
+       }\r
+       \r
+\r
        private<T extends Object> List<T> getOrdered(TreeMap<Integer, T> tree) {\r
                List<T> result = new ArrayList<T>();\r
                for (T value : tree.values()){\r