change doSpecimen to doEcoFacts
[cdmlib-apps.git] / app-import / src / main / java / eu / etaxonomy / cdm / io / algaterra / AlgaTerraSpecimenImport.java
index 6fe5e03a2f567f290d8ff6d5695ec8904a112f93..94d45c84770820846666612f313a58e57ef8d195 100644 (file)
@@ -9,8 +9,6 @@
 \r
 package eu.etaxonomy.cdm.io.algaterra;\r
 \r
-import java.net.URI;\r
-import java.sql.Date;\r
 import java.sql.ResultSet;\r
 import java.sql.SQLException;\r
 import java.util.HashMap;\r
@@ -22,41 +20,38 @@ import java.util.UUID;
 import org.apache.commons.lang.StringUtils;\r
 import org.apache.log4j.Logger;\r
 import org.springframework.stereotype.Component;\r
-import org.springframework.transaction.TransactionStatus;\r
 \r
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade;\r
 import eu.etaxonomy.cdm.api.facade.DerivedUnitFacade.DerivedUnitType;\r
+import eu.etaxonomy.cdm.api.facade.DerivedUnitFacadeNotSupportedException;\r
 import eu.etaxonomy.cdm.io.algaterra.validation.AlgaTerraSpecimenImportValidator;\r
-import eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportBase;\r
 import eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportConfigurator;\r
 import eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportState;\r
 import eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelTaxonImport;\r
 import eu.etaxonomy.cdm.io.common.IOValidator;\r
 import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;\r
-import eu.etaxonomy.cdm.io.common.Source;\r
-import eu.etaxonomy.cdm.model.agent.Team;\r
 import eu.etaxonomy.cdm.model.common.CdmBase;\r
 import eu.etaxonomy.cdm.model.common.DefinedTermBase;\r
 import eu.etaxonomy.cdm.model.common.Language;\r
 import eu.etaxonomy.cdm.model.common.Marker;\r
 import eu.etaxonomy.cdm.model.common.MarkerType;\r
-import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;\r
-import eu.etaxonomy.cdm.model.common.TimePeriod;\r
+import eu.etaxonomy.cdm.model.common.TermVocabulary;\r
 import eu.etaxonomy.cdm.model.description.CategoricalData;\r
 import eu.etaxonomy.cdm.model.description.DescriptionBase;\r
 import eu.etaxonomy.cdm.model.description.Feature;\r
 import eu.etaxonomy.cdm.model.description.IndividualsAssociation;\r
-import eu.etaxonomy.cdm.model.description.SpecimenDescription;\r
+import eu.etaxonomy.cdm.model.description.MeasurementUnit;\r
+import eu.etaxonomy.cdm.model.description.Modifier;\r
+import eu.etaxonomy.cdm.model.description.QuantitativeData;\r
 import eu.etaxonomy.cdm.model.description.State;\r
+import eu.etaxonomy.cdm.model.description.StatisticalMeasure;\r
+import eu.etaxonomy.cdm.model.description.StatisticalMeasurementValue;\r
 import eu.etaxonomy.cdm.model.description.TaxonDescription;\r
 import eu.etaxonomy.cdm.model.description.TextData;\r
-import eu.etaxonomy.cdm.model.location.NamedArea;\r
-import eu.etaxonomy.cdm.model.location.Point;\r
-import eu.etaxonomy.cdm.model.location.ReferenceSystem;\r
-import eu.etaxonomy.cdm.model.location.TdwgArea;\r
-import eu.etaxonomy.cdm.model.location.WaterbodyOrCountry;\r
 import eu.etaxonomy.cdm.model.name.BotanicalName;\r
 import eu.etaxonomy.cdm.model.name.Rank;\r
+import eu.etaxonomy.cdm.model.occurrence.Collection;\r
+import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;\r
 import eu.etaxonomy.cdm.model.occurrence.FieldObservation;\r
 import eu.etaxonomy.cdm.model.reference.Reference;\r
 import eu.etaxonomy.cdm.model.taxon.Taxon;\r
@@ -65,31 +60,12 @@ import eu.etaxonomy.cdm.model.taxon.TaxonBase;
 \r
 /**\r
  * @author a.mueller\r
- * @created 20.03.2008\r
- * @version 1.0\r
+ * @created 01.09.2012\r
  */\r
 @Component\r
-public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {\r
+public class AlgaTerraSpecimenImport  extends AlgaTerraSpecimenImportBase {\r
        private static final Logger logger = Logger.getLogger(AlgaTerraSpecimenImport.class);\r
 \r
-       public static final String FIELD_OBSERVATION_NAMESPACE = "FieldObservation";\r
-       public static final String TERMS_NAMESPACE = "ALGA_TERRA_TERMS";\r
-       \r
-       //move to transformrer\r
-       final static UUID uuidMarkerAlkalinity = UUID.fromString("e52d0ea2-0c1f-4d95-ae6d-e21ab317c594");  \r
-       final static UUID uuidRefSystemGps = UUID.fromString("c23e4928-c137-4e4a-b6ab-b430da3d0b94");  \r
-       final static UUID uuidFeatureSpecimenCommunity = UUID.fromString("3ff5b1ab-3999-4b5a-b8f7-01fd2f6c12c7");\r
-       final static UUID uuidFeatureAdditionalData = UUID.fromString("0ac82ab8-2c2b-4953-98eb-a9f718eb9c57");\r
-       \r
-       final static UUID uuidVocAlgaTerraClimate = UUID.fromString("b0a677c6-8bb6-43f4-b1b8-fc377a10feb5");\r
-       final static UUID uuidVocAlgaTerraHabitat = UUID.fromString("06f30114-e19c-4e7d-a8e5-5488c41fcbc5");\r
-       final static UUID uuidVocAlgaTerraLifeForm = UUID.fromString("3c0b194e-809c-4b42-9498-6ff034066ed7");\r
-       \r
-       final static UUID uuidFeatureAlgaTerraClimate = UUID.fromString("8754674c-9ab9-4f28-95f1-91eeee2314ee");\r
-       final static UUID uuidFeatureAlgaTerraHabitat = UUID.fromString("7def3fc2-cdc5-4739-8e13-62edbd053415");\r
-       final static UUID uuidFeatureAlgaTerraLifeForm = UUID.fromString("9b657901-1b0d-4a2a-8d21-dd8c1413e2e6");\r
-       \r
-       \r
        \r
        private static int modCount = 5000;\r
        private static final String pluralString = "specimen and observation";\r
@@ -121,10 +97,10 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
         */\r
        @Override\r
        protected String getRecordQuery(BerlinModelImportConfigurator config) {\r
-                       String strQuery =   //DISTINCT because otherwise emOccurrenceSource creates multiple records for a single distribution \r
-            " SELECT PTaxon.RIdentifier as taxonId, Fact.FactId, Fact.RecordBasis, EcoFact.*, " + \r
+                       String strQuery =   \r
+            " SELECT PTaxon.RIdentifier as taxonId, Fact.FactId, Fact.RecordBasis, EcoFact.*, EcoFact.EcoFactId as unitId, " + \r
                " tg.ID AS GazetteerId, tg.L2Code, tg.L3Code, tg.L4Code, tg.Country, tg.ISOCountry, " +\r
-               " ec.UUID as climateUuid, eh.UUID as habitatUuid, elf.UUID as lifeFormUuid" +\r
+               " ec.UUID as climateUuid, eh.UUID as habitatUuid, elf.UUID as lifeFormUuid " +\r
             " FROM Fact " + \r
                  " INNER JOIN EcoFact ON Fact.ExtensionFk = EcoFact.EcoFactId " +\r
                  " INNER JOIN PTaxon ON dbo.Fact.PTNameFk = dbo.PTaxon.PTNameFk AND dbo.Fact.PTRefFk = dbo.PTaxon.PTRefFk " +\r
@@ -154,7 +130,7 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                Set<TaxonBase> taxaToSave = new HashSet<TaxonBase>();\r
                \r
                Map<String, TaxonBase> taxonMap = (Map<String, TaxonBase>) partitioner.getObjectMap(BerlinModelTaxonImport.NAMESPACE);\r
-               Map<String, FieldObservation> fieldObservationMap = (Map<String, FieldObservation>) partitioner.getObjectMap(FIELD_OBSERVATION_NAMESPACE);\r
+               Map<String, DerivedUnit> ecoFactDerivedUnitMap = (Map<String, DerivedUnit>) partitioner.getObjectMap(ECO_FACT_DERIVED_UNIT_NAMESPACE);\r
                \r
                ResultSet rs = partitioner.getResultSet();\r
 \r
@@ -178,12 +154,15 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                                        Reference<?> sourceRef = state.getTransactionalSourceReference();\r
                                \r
                                        //facade\r
-                                       FieldObservation fieldObservation = getFieldObservation(ecoFactId, fieldObservationMap);\r
                                        DerivedUnitType type = makeDerivedUnitType(recordBasis);\r
-                                       DerivedUnitFacade facade = DerivedUnitFacade.NewInstance(type, fieldObservation);\r
-\r
+                                       DerivedUnitFacade facade = getDerivedUnit(state, ecoFactId, ecoFactDerivedUnitMap, type);\r
+                                       \r
                                        //field observation\r
-                                       handleSingleSpecimen(rs, facade, state);\r
+                                       handleSingleSpecimen(rs, facade, state, partitioner);\r
+                                       \r
+                                       handleEcoFactSpecificSpecimen(rs,facade, state);\r
+                                       \r
+                                       state.setCurrentFieldObservationNotNew(false);\r
                                        \r
                                        //description element\r
                                        TaxonDescription taxonDescription = getTaxonDescription(state, newTaxonId, taxonMap, factId, sourceRef);\r
@@ -214,214 +193,77 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                        return false;\r
                }\r
        }\r
+       \r
+       protected String getDerivedUnitNameSpace(){\r
+               return ECO_FACT_DERIVED_UNIT_NAMESPACE;\r
+       }\r
 \r
 \r
 \r
-\r
-       /**\r
-        * Creates the vocabularies and the features for Climate, Habitat and Lifeform\r
-        * @param state\r
-        * @throws SQLException\r
-        */\r
-       private void makeVocabulariesAndFeatures(AlgaTerraImportState state) throws SQLException {\r
-               String abbrevLabel = null;\r
-               URI uri = null;\r
+       private void handleEcoFactSpecificSpecimen(ResultSet rs, DerivedUnitFacade facade, AlgaTerraImportState state) throws SQLException {\r
                \r
-               if (! state.isSpecimenVocabulariesCreated()){\r
-                       \r
-                       TransactionStatus txStatus = this.startTransaction();\r
+               Object alkalinityFlag = rs.getBoolean("AlkalinityFlag");\r
                \r
-                       boolean isOrdered = true;\r
-                       OrderedTermVocabulary<State> climateVoc = (OrderedTermVocabulary)getVocabulary(uuidVocAlgaTerraClimate, "Climate", "Climate", abbrevLabel, uri, isOrdered, null);\r
-                       OrderedTermVocabulary<State> habitatVoc = (OrderedTermVocabulary)getVocabulary(uuidVocAlgaTerraHabitat, "Habitat", "Habitat", abbrevLabel, uri, isOrdered, null);\r
-                       OrderedTermVocabulary<State> lifeformVoc = (OrderedTermVocabulary)getVocabulary(uuidVocAlgaTerraLifeForm, "Lifeform", "Lifeform", abbrevLabel, uri, isOrdered, null);\r
-                       \r
-                       \r
-                       Feature feature = getFeature(state, uuidFeatureAlgaTerraClimate, "Climate","Climate", null, null);\r
-                       feature.setSupportsCategoricalData(true);\r
-                       \r
-                       feature = getFeature(state, uuidFeatureAlgaTerraLifeForm, "LifeForm","LifeForm", null, null);\r
-                       feature.setSupportsCategoricalData(true);\r
-                       \r
-                       feature = Feature.HABITAT();\r
-                       feature.setSupportsCategoricalData(true);\r
-                       getTermService().saveOrUpdate(feature);\r
-                       \r
-                       Source source = state.getAlgaTerraConfigurator().getSource();\r
-                       \r
-                       String climateSql = "SELECT * FROM EcoClimate";\r
-                       ResultSet rs = source.getResultSet(climateSql);\r
-                       while (rs.next()){\r
-                               String climate = rs.getString("Climate");\r
-                               String description = rs.getString("Description");\r
-                               Integer id = rs.getInt("ClimateId");\r
-                               UUID uuid = UUID.fromString(rs.getString("UUID"));\r
-                               State stateTerm = getStateTerm(state, uuid, climate, description, null, climateVoc);\r
-                               addOriginalSource(stateTerm, id.toString(), "EcoClimate", state.getConfig().getSourceReference());\r
-                               getTermService().saveOrUpdate(stateTerm);\r
-                       }\r
-                       \r
-                       String habitatSql = "SELECT * FROM EcoHabitat";\r
-                       rs = source.getResultSet(habitatSql);\r
-                       while (rs.next()){\r
-                               String habitat = rs.getString("Habitat");\r
-                               String description = rs.getString("Description");\r
-                               Integer id = rs.getInt("HabitatId");\r
-                               UUID uuid = UUID.fromString(rs.getString("UUID"));\r
-                               State stateTerm = getStateTerm(state, uuid, habitat, description, null, habitatVoc);\r
-                               addOriginalSource(stateTerm, id.toString(), "EcoHabitat", state.getConfig().getSourceReference());\r
-                               getTermService().saveOrUpdate(stateTerm);\r
-                       }\r
-                       \r
-                       String lifeformSql = "SELECT * FROM EcoLifeForm";\r
-                       rs = source.getResultSet(lifeformSql);\r
-                       while (rs.next()){\r
-                               String lifeform = rs.getString("LifeForm");\r
-                               String description = rs.getString("Description");\r
-                               Integer id = rs.getInt("LifeFormId");\r
-                               UUID uuid = UUID.fromString(rs.getString("UUID"));\r
-                               State stateTerm = getStateTerm(state, uuid, lifeform, description, null, lifeformVoc);\r
-                               addOriginalSource(stateTerm, id.toString(), "EcoLifeForm", state.getConfig().getSourceReference());\r
-                               getTermService().saveOrUpdate(stateTerm);\r
-                       }\r
-                       \r
-                       this.commitTransaction(txStatus);\r
-                       \r
-                       state.setSpecimenVocabulariesCreated(true);\r
+               //alkalinity marker\r
+               if (alkalinityFlag != null){\r
+                       MarkerType alkalinityMarkerType = getMarkerType(state, uuidMarkerAlkalinity, "Alkalinity", "Alkalinity", null);\r
+                       boolean alkFlag = Boolean.valueOf(alkalinityFlag.toString());\r
+                       Marker alkalinityMarker = Marker.NewInstance(alkalinityMarkerType, alkFlag);\r
+                       facade.getFieldObservation(true).addMarker(alkalinityMarker);\r
                }\r
                \r
-       }\r
-\r
+               \r
+               DescriptionBase<?> fieldDescription = getFieldObservationDescription(facade);\r
 \r
+               //habitat, ecology, community, etc.\r
+               String habitat = rs.getString("HabitatExplanation");\r
+               \r
+               if (isNotBlank(habitat)){\r
+                       Feature habitatExplanation = getFeature(state, uuidFeatureHabitatExplanation, "Habitat Explanation", "HabitatExplanation", null, null);\r
+                       TextData textData = TextData.NewInstance(habitatExplanation);\r
+                       textData.putText(Language.DEFAULT(), habitat);\r
+                       fieldDescription.addElement(textData);\r
+               }\r
+               \r
+               String community = rs.getString("Comunity");\r
+               if (isNotBlank(community)){\r
+                       Feature communityFeature = getFeature(state, uuidFeatureSpecimenCommunity, "Community", "The community of a specimen (e.g. other algae in the same sample)", null, null);\r
+                       TextData textData = TextData.NewInstance(communityFeature);\r
+                       textData.putText(Language.DEFAULT(), community);\r
+                       fieldDescription.addElement(textData);\r
+               }\r
 \r
-       private void handleSingleSpecimen(ResultSet rs, DerivedUnitFacade facade, AlgaTerraImportState state) throws SQLException {\r
-               //CollectionFk, Collector, AltitudeMethod, \r
-       //ISOCountrySub, CreatedWhen/Who/Updated/who\r
-       \r
-       //P1-10Value/Unit/Parameter/Method\r
+               String additionalData = rs.getString("AdditionalData");\r
+               if (isNotBlank(additionalData)){  //or handle it as Annotation ??\r
+                       Feature additionalDataFeature = getFeature(state, uuidFeatureAdditionalData, "Additional Data", "Additional Data", null, null);\r
+                       TextData textData = TextData.NewInstance(additionalDataFeature);\r
+                       textData.putText(Language.DEFAULT(), additionalData);\r
+                       fieldDescription.addElement(textData);\r
+               }\r
                \r
-               try {\r
-                       Object alkalinityFlag = rs.getBoolean("AlkalinityFlag");\r
-                       \r
-                       String locality = rs.getString("Locality");\r
-                       Double latitude = nullSafeDouble(rs, "Latitude");\r
-                       Double longitude = nullSafeDouble(rs, "Longitude");\r
-                       Integer errorRadius = nullSafeInt(rs,"Prec");\r
-                       String geoCodeMethod = rs.getString("GeoCodeMethod");\r
-                       \r
-                       Integer altitude = nullSafeInt(rs, "Altitude");\r
-                       Integer lowerAltitude = nullSafeInt(rs,"AltitudeLowerValue");\r
-                       String altitudeUnit = rs.getString("AltitudeUnit");\r
-                       Double depth = nullSafeDouble(rs, "Depth");\r
-                       Double depthLow = nullSafeDouble(rs, "DepthLow");\r
-                               \r
-                       String collectorsNumber = rs.getString("CollectorsNumber");\r
-                       Date collectionDateStart = rs.getDate("CollectionDate");\r
-                       Date collectionDateEnd = rs.getDate("CollectionDateEnd");\r
-                       \r
-                       String climateUuid = rs.getString("climateUuid");\r
-                       String habitatUuid = rs.getString("habitatUuid");\r
-                       String lifeFormUuid = rs.getString("lifeFormUuid");\r
-                       \r
-                       String habitat = rs.getString("HabitatExplanation");\r
-                       String community = rs.getString("Comunity");\r
-                       String additionalData = rs.getString("AdditionalData");\r
-                       \r
-                       \r
-                       \r
-                       FieldObservation fieldObservation = facade.innerFieldObservation();\r
-                       \r
-                       //alkalinity marker\r
-                       if (alkalinityFlag != null){\r
-                               MarkerType alkalinityMarkerType = getMarkerType(state, uuidMarkerAlkalinity, "Alkalinity", "Alkalinity", null);\r
-                               boolean alkFlag = Boolean.valueOf(alkalinityFlag.toString());\r
-                               Marker alkalinityMarker = Marker.NewInstance(alkalinityMarkerType, alkFlag);\r
-                               fieldObservation.addMarker(alkalinityMarker);\r
-                       }\r
-                       \r
-                       //location\r
-                       facade.setLocality(locality);\r
-                               \r
-                       //exact location\r
-                       ReferenceSystem referenceSystem = makeRefrenceSystem(geoCodeMethod, state);\r
-                       Point exactLocation = Point.NewInstance(longitude, latitude, referenceSystem, errorRadius);\r
-                       facade.setExactLocation(exactLocation);\r
-                       \r
-                       //altitude, depth\r
-                       if (StringUtils.isNotBlank(altitudeUnit) && ! altitudeUnit.trim().equalsIgnoreCase("m")){\r
-                               logger.warn("Altitude unit is not [m] but: " +  altitudeUnit);\r
-                       }\r
-                       if ( altitude != null){\r
-                               if (lowerAltitude == null){\r
-                                       facade.setAbsoluteElevation(altitude);\r
-                               }else{\r
-                                       if (! facade.isEvenDistance(lowerAltitude, altitude)){\r
-                                               //FIXME there is a ticket for this\r
-                                               altitude = altitude + 1;\r
-                                               logger.warn("Current implementation of altitude does not allow uneven distances");\r
-                                       }\r
-                                       facade.setAbsoluteElevationRange(lowerAltitude,altitude);\r
-                               }\r
-                       }\r
-                       if ( depth != null){\r
-                               //FIXME needs model change to accept double #3072\r
-                               Integer intDepth = depth.intValue();\r
-                               if (depthLow == null){\r
-                                       facade.setDistanceToWaterSurface(intDepth);\r
-                               }else{\r
-                                       //FIXME range not yet in model #3074\r
-                                       facade.setDistanceToWaterSurface(intDepth);\r
-                               }\r
-                       }\r
-                       \r
-                       //habitat, ecology, community, etc.\r
-                       DescriptionBase<?> fieldDescription = getFieldObservationDescription(facade);\r
-                       addCategoricalValue(state, fieldDescription, climateUuid, uuidFeatureAlgaTerraClimate);\r
-                       addCategoricalValue(state, fieldDescription, habitatUuid, Feature.HABITAT().getUuid());\r
-                       addCategoricalValue(state, fieldDescription, lifeFormUuid, uuidFeatureAlgaTerraLifeForm);\r
-                       \r
-                       if (isNotBlank(habitat)){\r
-                               //FIXME\r
-                               facade.setEcology(habitat);  //or use an own feature ??\r
-                       }\r
-                       if (isNotBlank(community)){\r
-                               Feature communityFeature = getFeature(state, uuidFeatureSpecimenCommunity, "Community", "The community of a specimen (e.g. other algae in the same sample)", null, null);\r
-                               TextData textData = TextData.NewInstance(communityFeature);\r
-                               textData.putText(Language.DEFAULT(), community);\r
-                               getFieldObservationDescription(facade).addElement(textData);\r
-                       }\r
-                       if (isNotBlank(additionalData)){  //or handle it as Annotation ??\r
-                               Feature additionalDataFeature = getFeature(state, uuidFeatureAdditionalData, "Additional Data", "Additional Data", null, null);\r
-                               TextData textData = TextData.NewInstance(additionalDataFeature);\r
-                               textData.putText(Language.DEFAULT(), additionalData);\r
-                               getFieldObservationDescription(facade).addElement(textData);\r
-                       }\r
-                       \r
-                       //field\r
-                       facade.setFieldNumber(collectorsNumber);\r
-                       TimePeriod gatheringPeriod = TimePeriod.NewInstance(collectionDateStart, collectionDateEnd);\r
-                       facade.setGatheringPeriod(gatheringPeriod);\r
-                       handleCollectorTeam(state, facade, rs);\r
-                       \r
-                       //areas\r
-                       makeAreas(state, rs, facade);\r
-                       \r
-                       //parameters\r
-                       //TODO\r
-                       \r
-                       //notes\r
-                       //TODO is this an annotation on field observation or on the derived unit?\r
-                       \r
-                       //TODO id, created for fact +  ecoFact\r
-                       //      this.doIdCreatedUpdatedNotes(state, descriptionElement, rs, id, namespace);\r
+               String climateUuid = rs.getString("climateUuid");\r
+               String habitatUuid = rs.getString("habitatUuid");\r
+               String lifeFormUuid = rs.getString("lifeFormUuid");\r
+               \r
+               addCategoricalValue(state, fieldDescription, climateUuid, uuidFeatureAlgaTerraClimate);\r
+               addCategoricalValue(state, fieldDescription, habitatUuid, Feature.HABITAT().getUuid());\r
+               addCategoricalValue(state, fieldDescription, lifeFormUuid, uuidFeatureAlgaTerraLifeForm);\r
                \r
-               } catch (IllegalArgumentException e) {\r
-                       throw e;\r
+               \r
+               //collection\r
+               String voucher = rs.getString("Voucher");\r
+               if (StringUtils.isNotBlank(voucher)){\r
+                       facade.setAccessionNumber(voucher);\r
                }\r
-       \r
+               \r
+               //parameters\r
+               makeParameter(state, rs, getFieldObservationDescription(facade));\r
+\r
        }\r
 \r
 \r
+\r
+\r
        private void addCategoricalValue(AlgaTerraImportState importState, DescriptionBase description, String uuidTerm, UUID featureUuid) {\r
                if (uuidTerm != null){\r
                        State state = this.getStateTerm(importState, UUID.fromString(uuidTerm));\r
@@ -431,117 +273,153 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                }\r
        }\r
 \r
-\r
-       private void handleCollectorTeam(AlgaTerraImportState state, DerivedUnitFacade facade, ResultSet rs) throws SQLException {\r
-               // FIXME parsen\r
-               String collector = rs.getString("Collector");\r
-               Team team = Team.NewTitledInstance(collector, collector);\r
-               facade.setCollector(team);\r
-               \r
-               \r
+       private void makeParameter(AlgaTerraImportState state, ResultSet rs, DescriptionBase<?> descriptionBase) throws SQLException {\r
+               for (int i = 1; i <= 10; i++){\r
+                       String valueStr = rs.getString(String.format("P%dValue", i));\r
+                       String unitStr = rs.getString(String.format("P%dUnit", i));\r
+                       String parameter = rs.getString(String.format("P%dParameter", i));\r
+                       String method = rs.getString(String.format("P%dMethod", i));\r
+                       \r
+                       //method\r
+                       if (StringUtils.isNotBlank(method)){\r
+                               logger.warn("Methods not yet handled: " + method);\r
+                       }\r
+                       //parameter\r
+                       TermVocabulary<Feature> vocParameter = getVocabulary(uuidVocParameter, "Feature vocabulary for AlgaTerra measurement parameters", "Parameters", null, null, false, Feature.COMMON_NAME());\r
+                       if (StringUtils.isNotBlank(parameter)){\r
+                               UUID featureUuid = getParameterFeatureUuid(state, parameter);\r
+                               Feature feature = getFeature(state, featureUuid, parameter, parameter, null, vocParameter);\r
+                               QuantitativeData quantData = QuantitativeData.NewInstance(feature);\r
+                               \r
+                               //unit\r
+                               MeasurementUnit unit = getMeasurementUnit(state, unitStr);\r
+                               quantData.setUnit(unit);\r
+                               try {\r
+                                       \r
+                                       Set<Modifier> valueModifier = new HashSet<Modifier>();\r
+                                       valueStr = normalizeAndModifyValue(state, valueStr, valueModifier);\r
+                                       //value\r
+                                       Float valueFlt = Float.valueOf(valueStr);  //TODO maybe change model to Double ??\r
+                                       \r
+                                       StatisticalMeasure measureSingleValue = getStatisticalMeasure(state, uuidStatMeasureSingleValue, "Value", "Single measurement value", null, null);\r
+                                       StatisticalMeasurementValue value = StatisticalMeasurementValue.NewInstance(measureSingleValue, valueFlt); \r
+                                       quantData.addStatisticalValue(value);\r
+                                       descriptionBase.addElement(quantData);\r
+                                       \r
+                               } catch (NumberFormatException e) {\r
+                                       logger.warn(String.format("Value '%s' can't be converted to double. Parameter %s not imported.", valueStr, parameter));\r
+                               }\r
+                       }else if (isNotBlank(valueStr) || isNotBlank(unitStr) ){\r
+                               logger.warn("There is value or unit without parameter: " + i);\r
+                       }\r
+                       \r
+                       \r
+               }\r
                \r
        }\r
 \r
-       private void makeAreas(AlgaTerraImportState state, ResultSet rs, DerivedUnitFacade facade) throws SQLException {\r
-               Object gazetteerId = rs.getObject("GazetteerId");\r
-               if (gazetteerId != null){\r
-                       //TDWG\r
-                       NamedArea tdwgArea;\r
-                       String tdwg4 = rs.getString("L4Code");\r
-                       if (isNotBlank(tdwg4)){\r
-                               tdwgArea = TdwgArea.getAreaByTdwgAbbreviation(tdwg4);\r
-                       }else{\r
-                               String tdwg3 = rs.getString("L3Code");\r
-                               if (isNotBlank(tdwg3)){\r
-                                       tdwgArea = TdwgArea.getAreaByTdwgAbbreviation(tdwg3);\r
-                               }else{\r
-                                       Integer tdwg2 = rs.getInt("L2Code");                            \r
-                                       tdwgArea = TdwgArea.getAreaByTdwgAbbreviation(String.valueOf(tdwg2));\r
-                               }\r
-                       }\r
-                       if (tdwgArea == null){\r
-                               logger.warn("TDWG area could not be defined for gazetterId: " + gazetteerId);\r
-                       }else{\r
-                               facade.addCollectingArea(tdwgArea);\r
-                       }\r
-                       \r
-                       //Countries\r
-                       WaterbodyOrCountry country = null;\r
-                       String isoCountry = rs.getString("ISOCountry");\r
-                       String countryStr = rs.getString("Country");\r
-                       if (isNotBlank(isoCountry)){\r
-                               country = WaterbodyOrCountry.getWaterbodyOrCountryByIso3166A2(isoCountry);\r
-                       }else if (isNotBlank(countryStr)){\r
-                               logger.warn("Country exists but no ISO code");\r
-                       }\r
-                       if (country == null){\r
-                               logger.warn("Country does not exist for GazetteerID " + gazetteerId);\r
-                       }else{\r
-                               facade.setCountry(country);\r
-                       }\r
-                       \r
-               }\r
-           \r
-               //Waterbody\r
-               WaterbodyOrCountry waterbody = null;\r
-               String waterbodyStr = rs.getString("WaterBody");\r
-               if (isNotBlank(waterbodyStr)){\r
-                       if (waterbodyStr.equals("Atlantic Ocean")){\r
-                               waterbody = WaterbodyOrCountry.ATLANTICOCEAN();\r
-                       }else{\r
-                               logger.warn("Waterbody not recognized: " + waterbody);\r
-                       }\r
-                       if (waterbody != null){\r
-                               facade.addCollectingArea(waterbody);\r
-                       }\r
-               }\r
-\r
-               \r
-               //countries sub\r
-               //TODO\r
+       private String normalizeAndModifyValue(AlgaTerraImportState state, String valueStr, Set<Modifier> valueModifier) {\r
+               valueStr = valueStr.replace(",", ".");\r
+               if (valueStr.startsWith("<")){\r
+                       TermVocabulary<Modifier> measurementValueModifierVocabulary = getVocabulary(uuidMeasurementValueModifier, "Measurement value modifier", "Measurement value modifier", null, null, false, Modifier.NewInstance());\r
+                       Modifier modifier = getModifier(state, uuidModifierLowerThan, "Lower", "Lower than the given measurement value", "<", measurementValueModifierVocabulary);\r
+                       valueModifier.add(modifier);\r
+                       valueStr = valueStr.replace("<", "");\r
+               }\r
+               if (valueStr.startsWith(">")){\r
+                       TermVocabulary<Modifier> measurementValueModifierVocabulary = getVocabulary(uuidMeasurementValueModifier, "Measurement value modifier", "Measurement value modifier", null, null, false, Modifier.NewInstance());\r
+                       Modifier modifier = getModifier(state, uuidModifierGreaterThan, "Lower", "Lower than the given measurement value", "<", measurementValueModifierVocabulary);\r
+                       valueModifier.add(modifier);\r
+                       valueStr = valueStr.replace(">", "");\r
+               }\r
+               return valueStr;\r
        }\r
 \r
-       private DescriptionBase getFieldObservationDescription(DerivedUnitFacade facade) {\r
-               Set<DescriptionBase> descriptions = facade.innerFieldObservation().getDescriptions();\r
-               for (DescriptionBase desc : descriptions){\r
-                       if (desc.isImageGallery() == false){\r
-                               return desc;\r
-                       }\r
+\r
+\r
+       private UUID getParameterFeatureUuid(AlgaTerraImportState state, String key) {\r
+               //TODO define some UUIDs in Transformer\r
+               UUID uuid = state.getParameterFeatureUuid(key);\r
+               if (uuid == null){\r
+                       uuid = UUID.randomUUID();\r
+                       state.putParameterFeatureUuid(key, uuid);\r
                }\r
-               SpecimenDescription specDesc = SpecimenDescription.NewInstance(facade.innerFieldObservation());\r
-               descriptions.add(specDesc);\r
-               return specDesc;\r
+               return uuid;\r
        }\r
 \r
-       private ReferenceSystem makeRefrenceSystem(String geoCodeMethod, AlgaTerraImportState state) {\r
-               if (StringUtils.isBlank(geoCodeMethod)){\r
-                       return null;\r
-               }else if(geoCodeMethod.startsWith("GPS")){\r
-                       getReferenceSystem(state, uuidRefSystemGps, "GPS", "GPS", "GPS", ReferenceSystem.GOOGLE_EARTH().getVocabulary());\r
-                       return ReferenceSystem.WGS84(); \r
-               }else if(geoCodeMethod.startsWith("Google")){\r
-                       return ReferenceSystem.GOOGLE_EARTH();\r
-               }else if(geoCodeMethod.startsWith("Map")){\r
-                       logger.warn("Reference system " +  geoCodeMethod +  " not yet supported.");\r
-                       return null;\r
-               }else if(geoCodeMethod.startsWith("WikiProjekt Georeferenzierung") || geoCodeMethod.startsWith("http://toolserver.org/~geohack/geohack.php") ){\r
-                       return ReferenceSystem.WGS84();\r
-               }else {\r
-                       logger.warn("Reference system " +  geoCodeMethod +  " not yet supported.");\r
+\r
+\r
+       /**\r
+        * TODO move to InputTransformerBase\r
+        * @param state\r
+        * @param unitStr\r
+        * @return\r
+        */\r
+       private MeasurementUnit getMeasurementUnit(AlgaTerraImportState state, String unitStr) {\r
+               if (StringUtils.isNotBlank(unitStr)){\r
+                       UUID uuidMeasurementUnitMgL = UUID.fromString("7ac302c5-3cbd-4334-964a-bf5d11eb9ead");\r
+                       UUID uuidMeasurementUnitMolMol = UUID.fromString("96b78d78-3e49-448f-8100-e7779b71dd53");\r
+                       UUID uuidMeasurementUnitMicroMolSiL = UUID.fromString("2cb8bc85-a4af-42f1-b80b-34c36c9f75d4");\r
+                       UUID uuidMeasurementUnitMicroMolL = UUID.fromString("a631f62e-377e-405c-bd1a-76885b13a72b");\r
+                       UUID uuidMeasurementUnitDegreeC = UUID.fromString("55222aec-d5be-413e-8db7-d9a48c316c6c");\r
+                       UUID uuidMeasurementUnitPercent = UUID.fromString("3ea3110e-f048-4bed-8bfe-33c60f63626f");\r
+                       UUID uuidMeasurementUnitCm = UUID.fromString("3ea3110e-f048-4bed-8bfe-33c60f63626f");\r
+                       UUID uuidMeasurementUnitMicroSiCm = UUID.fromString("3ea3110e-f048-4bed-8bfe-33c60f63626f");\r
+                       \r
+                       \r
+                       if (unitStr.equalsIgnoreCase("mg/L")){\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitMgL, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("mol/mol")){\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitMolMol, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("\u00B5mol Si/L")){   //µmol Si/L\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitMicroMolSiL, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("\u00B5mol/L")){             //µmol/L\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitMicroMolL, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("\u00B0C")){               //°C\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitDegreeC, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("%")){\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitPercent, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("cm")){\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitCm, unitStr, unitStr, unitStr, null);\r
+                       }else if (unitStr.equalsIgnoreCase("\u00B5S/cm")){   //µS/cm\r
+                               return getMeasurementUnit(state, uuidMeasurementUnitMicroSiCm, unitStr, unitStr, unitStr, null);\r
+                       }else{\r
+                               logger.warn("MeasurementUnit was not recognized");\r
+                               return null;\r
+                       }\r
+               }else{\r
                        return null;\r
                }\r
        }\r
 \r
-       private FieldObservation getFieldObservation(int ecoFactId, Map<String, FieldObservation> fieldObservationMap) {\r
+\r
+\r
+\r
+\r
+       /**\r
+        * @param state\r
+        * @param ecoFactId\r
+        * @param derivedUnitMap\r
+        * @param type \r
+        * @return\r
+        */\r
+       private DerivedUnitFacade getDerivedUnit(AlgaTerraImportState state, int ecoFactId, Map<String, DerivedUnit> derivedUnitMap, DerivedUnitType type) {\r
                String key = String.valueOf(ecoFactId);\r
-               FieldObservation fieldObservation = fieldObservationMap.get(key);\r
-               if (fieldObservation == null){\r
-                       fieldObservation = FieldObservation.NewInstance();\r
-                       \r
-                       fieldObservationMap.put(key, fieldObservation);\r
+               DerivedUnit derivedUnit = derivedUnitMap.get(key);\r
+               DerivedUnitFacade facade;\r
+               if (derivedUnit == null){\r
+                       facade = DerivedUnitFacade.NewInstance(type);\r
+                       derivedUnitMap.put(key, derivedUnit);\r
+               }else{\r
+                       try {\r
+                               facade = DerivedUnitFacade.NewInstance(derivedUnit);\r
+                       } catch (DerivedUnitFacadeNotSupportedException e) {\r
+                               logger.error(e.getMessage());\r
+                               facade = DerivedUnitFacade.NewInstance(type);\r
+                       }\r
                }\r
                \r
-               return fieldObservation;\r
+               return facade;\r
        }\r
        \r
        private Feature makeFeature(DerivedUnitType type) {\r
@@ -592,6 +470,7 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                        Set<String> taxonIdSet = new HashSet<String>();\r
                        Set<String> fieldObservationIdSet = new HashSet<String>();\r
                        Set<String> termsIdSet = new HashSet<String>();\r
+                       Set<String> collectionIdSet = new HashSet<String>();\r
                        \r
                        while (rs.next()){\r
                                handleForeignKey(rs, taxonIdSet, "taxonId");\r
@@ -599,6 +478,7 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                                handleForeignKey(rs, termsIdSet, "ClimateFk");\r
                                handleForeignKey(rs, termsIdSet, "HabitatFk");\r
                                handleForeignKey(rs, termsIdSet, "LifeFormFk");\r
+                               handleForeignKey(rs, collectionIdSet, "CollectionFk");\r
                        }\r
                        \r
                        //taxon map\r
@@ -609,21 +489,32 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
                        result.put(nameSpace, objectMap);\r
 \r
                        //field observation map map\r
-                       nameSpace = AlgaTerraSpecimenImport.FIELD_OBSERVATION_NAMESPACE;\r
+                       nameSpace = AlgaTerraSpecimenImport.ECO_FACT_FIELD_OBSERVATION_NAMESPACE;\r
                        cdmClass = FieldObservation.class;\r
-                       idSet = taxonIdSet;\r
+                       idSet = fieldObservationIdSet;\r
                        Map<String, FieldObservation> fieldObservationMap = (Map<String, FieldObservation>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);\r
                        result.put(nameSpace, fieldObservationMap);\r
 \r
+                       //collections\r
+                       nameSpace = AlgaTerraCollectionImport.NAMESPACE_COLLECTION;\r
+                       cdmClass = Collection.class;\r
+                       idSet = collectionIdSet;\r
+                       Map<String, Collection> collectionMap = (Map<String, Collection>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);\r
+                       result.put(nameSpace, collectionMap);\r
+\r
+                       //sub-collections\r
+                       nameSpace = AlgaTerraCollectionImport.NAMESPACE_SUBCOLLECTION;\r
+                       cdmClass = Collection.class;\r
+                       idSet = collectionIdSet;\r
+                       Map<String, Collection> subCollectionMap = (Map<String, Collection>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);\r
+                       result.put(nameSpace, subCollectionMap);\r
+\r
                        //terms\r
                        nameSpace = AlgaTerraSpecimenImport.TERMS_NAMESPACE;\r
                        cdmClass = FieldObservation.class;\r
-                       idSet = taxonIdSet;\r
+                       idSet = termsIdSet;\r
                        Map<String, DefinedTermBase> termMap = (Map<String, DefinedTermBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);\r
                        result.put(nameSpace, termMap);\r
-\r
-               \r
-                       \r
                        \r
                } catch (SQLException e) {\r
                        throw new RuntimeException(e);\r
@@ -701,7 +592,7 @@ public class AlgaTerraSpecimenImport  extends BerlinModelImportBase {
         * @see eu.etaxonomy.cdm.io.common.CdmIoBase#isIgnore(eu.etaxonomy.cdm.io.common.IImportConfigurator)\r
         */\r
        protected boolean isIgnore(BerlinModelImportState state){\r
-               return ! ((AlgaTerraImportState)state).getAlgaTerraConfigurator().isDoSpecimen();\r
+               return ! ((AlgaTerraImportState)state).getAlgaTerraConfigurator().isDoEcoFacts();\r
        }\r
        \r
 }\r