commit 8ef74e91262e5d2dabc664270e3ec637006ff662
Author: Andreas Müller <a.mueller@bgbm.org>
Date:   Mon Sep 24 21:25:37 2018 +0200

    ref #7346 use E+M area vocabulary for common names

diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelAreaImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelAreaImport.java
new file mode 100644
index 00000000..9513feb1
--- /dev/null
+++ b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelAreaImport.java
@@ -0,0 +1,410 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.cdm.io.berlinModel.in;
+
+import java.net.URI;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.log4j.Logger;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.TransactionStatus;
+
+import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
+import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelAreaImportValidator;
+import eu.etaxonomy.cdm.io.common.CdmImportBase;
+import eu.etaxonomy.cdm.io.common.IOValidator;
+import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
+import eu.etaxonomy.cdm.io.common.Source;
+import eu.etaxonomy.cdm.model.common.Annotation;
+import eu.etaxonomy.cdm.model.common.AnnotationType;
+import eu.etaxonomy.cdm.model.common.CdmBase;
+import eu.etaxonomy.cdm.model.common.ExtensionType;
+import eu.etaxonomy.cdm.model.common.Language;
+import eu.etaxonomy.cdm.model.common.Marker;
+import eu.etaxonomy.cdm.model.common.MarkerType;
+import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
+import eu.etaxonomy.cdm.model.common.OriginalSourceType;
+import eu.etaxonomy.cdm.model.common.TermType;
+import eu.etaxonomy.cdm.model.common.TermVocabulary;
+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.reference.Reference;
+
+
+/**
+ * @author a.mueller
+ * @since 20.03.2008
+ */
+@Component
+public class BerlinModelAreaImport  extends BerlinModelImportBase {
+
+    private static final long serialVersionUID = -2810052908318645219L;
+    private static final Logger logger = Logger.getLogger(BerlinModelAreaImport.class);
+
+	public static final String NAMESPACE = "emArea";
+
+	private static final String pluralString = "areas";
+	private static final String dbTableName = "emArea";  //??
+
+	public BerlinModelAreaImport(){
+		super(dbTableName, pluralString);
+	}
+
+	@Override
+	protected String getIdQuery(BerlinModelImportState state) {
+		String result = " SELECT AreaId FROM " + getTableName();
+//		if (StringUtils.isNotBlank(state.getConfig().getOccurrenceFilter())){
+//			result += " WHERE " +  state.getConfig().getOccurrenceFilter();
+//		}
+		return result;
+	}
+
+	@Override
+	protected String getRecordQuery(BerlinModelImportConfigurator config) {
+		String strQuery =
+		          " SELECT * "
+		        + " FROM emArea a "
+                + " WHERE (a.AreaId IN (" + ID_LIST_TOKEN + ")  )"
+//		        + " ORDER BY PTaxon.RIdentifier"
+                ;
+		return strQuery;
+	}
+
+	private Map<Integer, NamedArea> euroMedAreas = new HashMap<>();
+
+
+	private TermVocabulary<NamedArea> createEuroMedAreas(BerlinModelImportState state) throws SQLException {
+
+
+	    logger.warn("Start creating E+M areas");
+		Source source = state.getConfig().getSource();
+		Reference sourceReference = state.getConfig().getSourceReference();
+
+		TransactionStatus txStatus = this.startTransaction();
+
+		sourceReference = getSourceReference(sourceReference);
+
+		TermVocabulary<NamedArea> euroMedAreasVoc = makeEmptyEuroMedVocabulary();
+
+		MarkerType eurMarkerType = getMarkerType(state, BerlinModelTransformer.uuidEurArea, "eur", "eur Area", "eur", getEuroMedMarkerTypeVoc());
+		MarkerType euroMedAreaMarkerType = getMarkerType(state, BerlinModelTransformer.uuidEurMedArea, "EuroMedArea", "EuroMedArea", "EuroMedArea", getEuroMedMarkerTypeVoc());
+		ExtensionType isoCodeExtType = getExtensionType(state, BerlinModelTransformer.uuidIsoCode, "IsoCode", "IsoCode", "iso");
+		ExtensionType tdwgCodeExtType = getExtensionType(state, BerlinModelTransformer.uuidTdwgAreaCode, "TDWG code", "TDWG Area code", "tdwg");
+		ExtensionType mclCodeExtType = getExtensionType(state, BerlinModelTransformer.uuidMclCode, "MCL code", "MedCheckList code", "mcl");
+		NamedAreaLevel areaLevelTop = getNamedAreaLevel(state, BerlinModelTransformer.uuidEuroMedAreaLevelTop, "Euro+Med top area level", "Euro+Med top area level. This level is only to be used for the area representing the complete Euro+Med area", "e+m top", null);
+		NamedAreaLevel areaLevelEm1 = getNamedAreaLevel(state, BerlinModelTransformer.uuidEuroMedAreaLevelFirst, "Euro+Med 1. area level", "Euro+Med 1. area level", "e+m 1.", null);
+		NamedAreaLevel areaLevelEm2 = getNamedAreaLevel(state, BerlinModelTransformer.uuidEuroMedAreaLevelSecond, "Euro+Med 2. area level", "Euro+Med 2. area level", "Euro+Med 1. area level", null);
+
+
+		String sql = "SELECT * , CASE WHEN EMCode = 'EM' THEN 'a' ELSE 'b' END as isEM " +
+				" FROM emArea " +
+				" ORDER BY isEM, EMCode";
+		ResultSet rs = source.getResultSet(sql);
+
+		NamedArea euroMedArea = null;
+		NamedArea lastLevel1Area = null;
+
+		//euroMedArea (EMCode = 'EM')
+		rs.next();
+		euroMedArea = makeSingleEuroMedArea(rs, eurMarkerType, euroMedAreaMarkerType, isoCodeExtType, tdwgCodeExtType, mclCodeExtType,
+				areaLevelTop, areaLevelEm1 , areaLevelEm2, sourceReference, euroMedArea, lastLevel1Area);
+		euroMedAreasVoc.addTerm(euroMedArea);
+
+		//all other areas
+		while (rs.next()){
+			NamedArea newArea = makeSingleEuroMedArea(rs, eurMarkerType, euroMedAreaMarkerType,
+					isoCodeExtType, tdwgCodeExtType, mclCodeExtType,
+					areaLevelTop, areaLevelEm1 , areaLevelEm2, sourceReference, euroMedArea, lastLevel1Area);
+			if (newArea != null){
+    			euroMedAreasVoc.addTerm(newArea);
+    			if (newArea.getPartOf().equals(euroMedArea)){
+    				lastLevel1Area = newArea;
+    			}
+			}
+		}
+		emAreaFinetuning(euroMedAreasVoc, areaLevelEm2);
+
+		markAreasAsHidden(state, euroMedAreasVoc);
+
+	    getVocabularyService().saveOrUpdate(euroMedAreasVoc);
+
+		try {
+            commitTransaction(txStatus);
+        } catch (Exception e) {
+             e.printStackTrace();
+             logger.error("An exception occurred when trying to commit E+M Areas");
+        }
+		logger.warn("Created E+M areas");
+
+		return euroMedAreasVoc;
+	}
+
+	/**
+     * @param areaLevelEm2
+	 * @param euroMedAreas2
+     */
+    private void emAreaFinetuning(TermVocabulary<NamedArea> euroMedAreas, NamedAreaLevel areaLevelEm2) {
+        //CZ
+        NamedArea oldArea = euroMedAreas.getTermByIdInvocabulary("Cz");
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Cs"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sk"), areaLevelEm2);
+
+        //Ju
+        oldArea = euroMedAreas.getTermByIdInvocabulary("Ju");
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("BH"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Cg"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Ct"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Mk"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sl"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sr"), areaLevelEm2);
+
+        //IJ
+        oldArea = euroMedAreas.getTermByIdInvocabulary("IJ");
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Ir"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Jo"), areaLevelEm2);
+
+        //LS
+        oldArea = euroMedAreas.getTermByIdInvocabulary("LS");
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Le"), areaLevelEm2);
+        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sy"), areaLevelEm2);
+
+    }
+
+    //5.Mark areas to be hidden #3979 .5
+    private void markAreasAsHidden(BerlinModelImportState state, TermVocabulary<NamedArea> euroMedAreasVoc) {
+
+        try {
+
+            @SuppressWarnings("unchecked")
+            TermVocabulary<MarkerType> vocUserDefinedMarkerTypes = getVocabularyService().find(CdmImportBase.uuidUserDefinedMarkerTypeVocabulary);
+            if (vocUserDefinedMarkerTypes == null){
+                String message = "Marker type vocabulary could not be found. Hidden areas not added.";
+                logger.error(message);
+                System.out.println(message);
+            }
+            MarkerType hiddenAreaMarkerType = getMarkerType(state, BerlinModelTransformer.uuidHiddenArea,
+                    "Hidden Area","Used to hide distributions for the named areas in publications", null, getEuroMedMarkerTypeVoc());
+
+            //Add hidden area marker to Rs(C) and Rs(N)
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs);
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_B);
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_C);
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_E);
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_N);
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_K);
+            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_W);
+        } catch (Exception e) {
+            e.printStackTrace();
+            logger.error("Exception in markAreasAsHidden: " + e.getMessage());
+        }
+
+    }
+
+    private void hideArea(TermVocabulary<NamedArea> euroMedAreasVoc, MarkerType hiddenAreaMarkerType, UUID areaUuid) {
+        for (NamedArea namedArea : euroMedAreasVoc){
+            if (namedArea.getUuid().equals(areaUuid)){
+                namedArea.addMarker(Marker.NewInstance(hiddenAreaMarkerType, true));
+                return;
+            }
+        }
+    }
+
+    /**
+     * @param oldArea
+     * @param namedArea
+     * @param areaLevelEm2
+     */
+    private void makeSubterm(NamedArea oldArea, NamedArea namedArea, NamedAreaLevel areaLevelEm2) {
+        namedArea.setLevel(areaLevelEm2);
+        namedArea.setPartOf(oldArea);
+    }
+
+
+	/**
+	 * @param eurMarkerType
+	 * @param euroMedAreaMarkerType
+	 * @param isoCodeExtType
+	 * @param tdwgCodeExtType
+	 * @param mclCodeExtType
+	 * @param rs
+	 * @param areaLevelEm2
+	 * @param areaLevelEm1
+	 * @param areaLevelTop
+	 * @throws SQLException
+	 */
+	private NamedArea makeSingleEuroMedArea(ResultSet rs, MarkerType eurMarkerType,
+			MarkerType euroMedAreaMarkerType, ExtensionType isoCodeExtType,
+			ExtensionType tdwgCodeExtType, ExtensionType mclCodeExtType,
+			NamedAreaLevel areaLevelTop, NamedAreaLevel areaLevelEm1, NamedAreaLevel areaLevelEm2,
+			Reference sourceReference, NamedArea euroMedArea, NamedArea level1Area) throws SQLException {
+
+	    Integer areaId = rs.getInt("AreaId");
+		String emCode = nullSafeTrim(rs.getString("EMCode"));
+		String isoCode = nullSafeTrim(rs.getString("ISOCode"));
+		String tdwgCode = nullSafeTrim(rs.getString("TDWGCode"));
+		String unit = nullSafeTrim(rs.getString("Unit"));
+//				      ,[Status]
+//				      ,[OutputOrder]
+		boolean eurMarker = rs.getBoolean("eur");
+		boolean euroMedAreaMarker = rs.getBoolean("EuroMedArea");
+		String notes = nullSafeTrim(rs.getString("Notes"));
+		String mclCode = nullSafeTrim(rs.getString("MCLCode"));
+		String geoSearch = nullSafeTrim(rs.getString("NameForGeoSearch"));
+
+
+		if (isBlank(emCode)){
+			emCode = unit;
+		}
+
+		//uuid
+		UUID uuid = BerlinModelTransformer.getEMAreaUuid(emCode);
+		NamedArea area = (NamedArea)getTermService().find(uuid);
+		if (area == null){
+			//label
+			area = NamedArea.NewInstance(geoSearch, unit, emCode);
+			if (uuid != null){
+				area.setUuid(uuid);
+			}else{
+			    if (areaId == 211 || areaId == 213){  //Additional Azores and Canary Is. area are merged into primary area, see also area.addSource part below
+			        return null;
+			    }
+				logger.warn("Uuid for emCode could not be defined: " + emCode);
+			}
+		}
+
+
+		//code
+		area.setIdInVocabulary(emCode);
+		//notes
+		if (StringUtils.isNotEmpty(notes)){
+			area.addAnnotation(Annotation.NewInstance(notes, AnnotationType.EDITORIAL(), Language.DEFAULT()));
+		}
+		//markers
+		area.addMarker(Marker.NewInstance(eurMarkerType, eurMarker));
+		area.addMarker(Marker.NewInstance(euroMedAreaMarkerType, euroMedAreaMarker));
+
+		//extensions
+		if (isNotBlank(isoCode)){
+			area.addExtension(isoCode, isoCodeExtType);
+		}
+		if (isNotBlank(tdwgCode)){
+			area.addExtension(tdwgCode, tdwgCodeExtType);
+		}
+		if (isNotBlank(mclCode)){
+			area.addExtension(mclCode, mclCodeExtType);
+		}
+
+		//type
+		area.setType(NamedAreaType.ADMINISTRATION_AREA());
+
+		//source
+		area.addSource(OriginalSourceType.Import, String.valueOf(areaId), NAMESPACE, sourceReference, null);
+		//add duplicate area ids for canary
+		if (areaId == 624){ //Canary Is.
+		    area.addSource(OriginalSourceType.Import, String.valueOf(213), NAMESPACE, sourceReference, null);
+		}
+		if (areaId == 210){//Azores
+            area.addSource(OriginalSourceType.Import, String.valueOf(211), NAMESPACE, sourceReference, null);
+        }
+
+		//parent
+		if (euroMedArea != null){
+			if (emCode.contains("(")){
+				area.setPartOf(level1Area);
+				area.setLevel(areaLevelEm2);
+			}else{
+				area.setPartOf(euroMedArea);
+				area.setLevel(areaLevelEm1);
+			}
+		}else{
+			area.setLevel(areaLevelTop);
+		}
+		this.euroMedAreas.put(areaId, area);
+
+		//save
+		getTermService().saveOrUpdate(area);
+
+		return area;
+	}
+
+	private String nullSafeTrim(String string) {
+		if (string == null){
+			return null;
+		}else{
+			return string.trim();
+		}
+	}
+
+	/**
+	 *
+	 */
+	private TermVocabulary<NamedArea> makeEmptyEuroMedVocabulary() {
+		TermType type = TermType.NamedArea;
+		String description = "Euro+Med area vocabulary";
+		String label = "E+M areas";
+		String abbrev = null;
+		URI termSourceUri = null;
+		OrderedTermVocabulary<NamedArea> result = OrderedTermVocabulary.NewInstance(type, description, label, abbrev, termSourceUri);
+
+		result.setUuid(BerlinModelTransformer.uuidVocEuroMedAreas);
+		getVocabularyService().save(result);
+		return result;
+	}
+
+	@Override
+	public boolean doPartition(@SuppressWarnings("rawtypes") ResultSetPartitioner partitioner, BerlinModelImportState state)  {
+	    TermVocabulary<?> voc = getVocabularyService().find(BerlinModelTransformer.uuidVocEuroMedAreas);
+	    if (voc == null){
+	        try {
+	            createEuroMedAreas(state);
+	        } catch (SQLException e) {
+	            logger.warn("Exception when creating areas: " + e.getMessage());
+	            e.printStackTrace();
+	        }
+        }
+	    return true;
+	}
+
+
+	@Override
+	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
+
+		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
+		return result;
+	}
+
+	@Override
+	protected boolean doCheck(BerlinModelImportState state){
+		IOValidator<BerlinModelImportState> validator = new BerlinModelAreaImportValidator();
+		return validator.validate(state);
+	}
+
+
+	@Override
+	protected boolean isIgnore(BerlinModelImportState state){
+		if (! (state.getConfig().isDoOccurrence() || state.getConfig().isDoCommonNames())){
+			return true;
+		}else{
+			if (!this.checkSqlServerColumnExists(state.getConfig().getSource(), "emArea", "AreaId")){
+				logger.error("emArea table or AreaId column do not exist. Must ignore area import");
+				return true;
+			}else{
+				return false;
+			}
+		}
+	}
+
+}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelCommonNamesImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelCommonNamesImport.java
index ce80e9fb..4de7d53e 100644
--- a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelCommonNamesImport.java
+++ b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelCommonNamesImport.java
@@ -24,6 +24,7 @@ import java.util.UUID;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.TransactionStatus;
 
 import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
@@ -31,19 +32,19 @@ import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelCommonNamesImpor
 import eu.etaxonomy.cdm.io.common.IOValidator;
 import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
 import eu.etaxonomy.cdm.io.common.Source;
-import eu.etaxonomy.cdm.io.common.TdwgAreaProvider;
 import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.common.Extension;
 import eu.etaxonomy.cdm.model.common.ExtensionType;
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.Marker;
 import eu.etaxonomy.cdm.model.common.MarkerType;
+import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
 import eu.etaxonomy.cdm.model.common.Representation;
 import eu.etaxonomy.cdm.model.common.TermVocabulary;
 import eu.etaxonomy.cdm.model.description.CommonTaxonName;
 import eu.etaxonomy.cdm.model.description.DescriptionElementSource;
 import eu.etaxonomy.cdm.model.description.TaxonDescription;
-import eu.etaxonomy.cdm.model.location.Country;
 import eu.etaxonomy.cdm.model.location.NamedArea;
 import eu.etaxonomy.cdm.model.name.TaxonName;
 import eu.etaxonomy.cdm.model.reference.Reference;
@@ -74,7 +75,7 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 
 
 	//map that stores the regions (named areas) and makes them accessible via the regionFk
-	private Map<String, NamedArea> regionMap = new HashMap<>();
+	private Map<String, NamedArea> regionFkToAreaMap = new HashMap<>();
 
 	public BerlinModelCommonNamesImport(){
 		super(dbTableName, pluralString);
@@ -141,18 +142,22 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 	 */
 	private void makeRegions(BerlinModelImportState state) {
 		try {
-			SortedSet<Integer> regionFks = new TreeSet<>();
+			TransactionStatus tx = startTransaction();
+		    SortedSet<Integer> regionFks = new TreeSet<>();
 			Source source = state.getConfig().getSource();
 
 			//fill set with all regionFk from emCommonName.regionFks
-			getRegionFks(state, regionFks, source);
+			fillRegionFks(state, regionFks, source);
 			//concat filter string
 			String sqlWhere = getSqlWhere(regionFks);
 
 			//get E+M - TDWG Mapping
-			Map<String, String> emTdwgMap = getEmTdwgMap(source);
+//			Map<String, String> emTdwgMap = getEmTdwgMap(source);
+			Map<String, NamedArea> emCodeToAreaMap = getEmCodeToAreaMap(source);
 			//fill regionMap
-			fillRegionMap(state, sqlWhere, emTdwgMap);
+			fillRegionMap(state, sqlWhere, emCodeToAreaMap);
+
+			commitTransaction(tx);
 
 			return;
 		} catch (NumberFormatException e) {
@@ -167,7 +172,7 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 	}
 
 
-	@Override
+    @Override
 	public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state)  {
 		boolean success = true ;
 
@@ -269,7 +274,7 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 					}
 					commonTaxonNames.add(commonTaxonName);
 					regionFk = regionFk.trim();
-					NamedArea area = regionMap.get(regionFk);
+					NamedArea area = regionFkToAreaMap.get(regionFk);
 					if (area == null){
 						if (isNotBlank(regionFk) && regionFk != NO_REGION){
 							logger.warn("Area for " + regionFk + " not defined in regionMap.");
@@ -311,7 +316,6 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 	                commonTaxonName.addSource(source);
 				}
 
-
 				//MisNameRef
 				if (misNameRefFk != null){
 					//Taxon misappliedName = getMisappliedName(biblioRefMap, nomRefMap, misNameRefFk, taxon);
@@ -515,8 +519,11 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 	 * @throws SQLException
 	 *
 	 */
-	private void getRegionFks(BerlinModelImportState state, SortedSet<Integer> regionFks, Source source) throws SQLException {
-		String sql = " SELECT DISTINCT RegionFks FROM emCommonName";
+	private void fillRegionFks(BerlinModelImportState state, SortedSet<Integer> regionFks,
+	        Source source) throws SQLException {
+		String sql =
+		          " SELECT DISTINCT RegionFks "
+		        + " FROM emCommonName";
 		if (state.getConfig().getCommonNameFilter() != null){
 			sql += " WHERE " + state.getConfig().getCommonNameFilter();
 		}
@@ -553,12 +560,14 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 	 * @throws SQLException
 	 */
 	private void fillRegionMap(BerlinModelImportState state, String sqlWhere,
-			Map<String, String> emTdwgMap) throws SQLException {
-		Source source = state.getConfig().getSource();
-		String sql;
-		ResultSet rs;
-		sql = " SELECT RegionId, Region FROM emLanguageRegion WHERE RegionId IN ("+ sqlWhere+ ") ";
-		rs = source.getResultSet(sql);
+			Map<String, NamedArea> emCodeToAreaMap) throws SQLException {
+
+	    Source source = state.getConfig().getSource();
+		String sql =
+		      " SELECT RegionId, Region "
+		    + " FROM  emLanguageRegion "
+		    + " WHERE RegionId IN ("+ sqlWhere+ ") ";
+		ResultSet rs = source.getResultSet(sql);
 		while (rs.next()){
 			Object regionId = rs.getObject("RegionId");
 			String region = rs.getString("Region");
@@ -566,61 +575,30 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 			if (splitRegion.length <= 1){
 				NamedArea newArea = getNamedArea(state, null, region, "Language region '" + region + "'", null, null, null);
 //				getTermService().save(newArea);
-				regionMap.put(String.valueOf(regionId), newArea);
-				logger.info("Found new area: " +  region);
+				regionFkToAreaMap.put(String.valueOf(regionId), newArea);
+				logger.warn("Found new area: " +  region);
 			}else if (splitRegion.length == 2){
-				String emCode = splitRegion[1].trim();
-				String tdwgCode = emTdwgMap.get(emCode);
-				if (isNotBlank(tdwgCode) ){
-					NamedArea tdwgArea = getNamedArea(state, tdwgCode);
-					regionMap.put(String.valueOf(regionId), tdwgArea);
-				}else {
-					NamedArea area = getOtherAreas(state, emCode, tdwgCode);
-					if (area != null){
-						regionMap.put(String.valueOf(regionId), area);
-					}else{
-						logger.warn("emCode did not map to valid tdwgCode: " +  CdmUtils.Nz(emCode) + "->" + CdmUtils.Nz(tdwgCode));
-					}
+				String emCode = splitRegion[1].trim().replace(" ", "");
+
+				NamedArea area = emCodeToAreaMap.get(emCode);
+				if (area == null){
+				    String[] splits = emCode.split("/");
+				    if (splits.length == 2){
+				        area = emCodeToAreaMap.get(splits[0]);
+		            }
+				    if (area != null){
+				        logger.warn("emCode ambigous. Use larger area: " +  CdmUtils.Nz(emCode) + "->" + regionId);
+				    }else{
+				        logger.warn("emCode not recognized. Region not defined: " +  CdmUtils.Nz(emCode) + "->" + regionId);
+				    }
+				}
+				if (area != null){
+				    regionFkToAreaMap.put(String.valueOf(regionId), area);
 				}
 			}
 		}
 	}
 
-
-	/**
-	 * Returns the are for a given TDWG code. See {@link #getEmTdwgMap(Source)} for exceptions from
-	 * the TDWG code
-	 * @param state
-	 * @param tdwgCode
-	 */
-	private NamedArea getNamedArea(BerlinModelImportState state, String tdwgCode) {
-		NamedArea area;
-		if (tdwgCode.equalsIgnoreCase("Ab")){
-			area = getNamedArea(state, BerlinModelTransformer.uuidAb, "Azerbaijan & Nakhichevan", "Azerbaijan (including Nakhichevan)",  "Ab", null, null);
-			getTermService().saveOrUpdate(area);
-		}else if (tdwgCode.equalsIgnoreCase("Uk")){
-			area = getNamedArea(state, BerlinModelTransformer.uuidUk , "Ukraine & Crimea", "Ukraine (including Crimea)", "Uk", null, null);
-			getTermService().saveOrUpdate(area);
-		}else if (tdwgCode.equalsIgnoreCase("Rf")){
-//			area = getNamedArea(state, BerlinModelTransformer.uuidRf , "Ukraine & Crimea", "Ukraine (including Crimea)", "Uk", null, null);
-//			getTermService().saveOrUpdate(area);
-			area = Country.RUSSIANFEDERATION();
-		}else if (tdwgCode.equalsIgnoreCase("Gg")){
-			area = Country.GEORGIA();
-		}else if (tdwgCode.equalsIgnoreCase("SM")){
-            area = getNamedArea(state, BerlinModelTransformer.uuidSM , "Serbia & Montenegro", "Serbia & Montenegro", "SM", null, null);
-            getTermService().saveOrUpdate(area);
-        }else if (tdwgCode.equalsIgnoreCase("Tu")){
-            area = Country.TURKEYREPUBLICOF();
-        }else{
-			area = TdwgAreaProvider.getAreaByTdwgAbbreviation(tdwgCode);
-		}
-		if (area == null){
-			logger.warn("Area is null for " + tdwgCode);
-		}
-		return area;
-	}
-
 	/**
 	 * @param regionFks
 	 * @return
@@ -634,43 +612,107 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 		return sqlWhere;
 	}
 
-	/**
-	 * Returns a map which is filled by the emCode->TdwgCode mapping defined in emArea.
-	 * Some exceptions are defined for emCode 'Ab','Rf','Uk' and some additional mapping is added
-	 * for 'Ab / Ab(A)', 'Ga / Ga(F)', 'It / It(I)', 'Ar / Ar(A)','Hs / Hs(S)'
-	 * @param source
-	 * @throws SQLException
-	 */
-	private Map<String, String> getEmTdwgMap(Source source) throws SQLException {
-		String sql;
-		ResultSet rs;
-		Map<String, String> emTdwgMap = new HashMap<>();
-		sql = " SELECT EmCode, TDWGCode FROM emArea ";
-		rs = source.getResultSet(sql);
-		while (rs.next()){
-			String emCode = rs.getString("EMCode");
-			String TDWGCode = rs.getString("TDWGCode");
-			if (isNotBlank(emCode) ){
-				emCode = emCode.trim();
-				if (emCode.equalsIgnoreCase("Ab") || emCode.equalsIgnoreCase("Rf")||
-						emCode.equalsIgnoreCase("Uk") || emCode.equalsIgnoreCase("Gg")
-						|| emCode.equalsIgnoreCase("SM") || emCode.equalsIgnoreCase("Tu")){
-					emTdwgMap.put(emCode, emCode);
-				}else if (isNotBlank(TDWGCode)){
-					emTdwgMap.put(emCode, TDWGCode.trim());
-				}
-			}
-		}
-		emTdwgMap.put("Ab / Ab(A)", "Ab");
-		emTdwgMap.put("Ga / Ga(F)", "FRA-FR");
-		emTdwgMap.put("It / It(I)", "ITA");
-		emTdwgMap.put("Uk / Uk(U)", "Uk");
-		emTdwgMap.put("Ar / Ar(A)", "TCS-AR");
-		emTdwgMap.put("Hs / Hs(S)", "SPA-SP");
-		emTdwgMap.put("Hb / Hb(E)", "IRE-IR");
-
-		return emTdwgMap;
-	}
+//	/**
+//	 * Returns a map which is filled by the emCode->TdwgCode mapping defined in emArea.
+//	 * Some exceptions are defined for emCode 'Ab','Rf','Uk' and some additional mapping is added
+//	 * for 'Ab / Ab(A)', 'Ga / Ga(F)', 'It / It(I)', 'Ar / Ar(A)','Hs / Hs(S)'
+//	 * @param source
+//	 * @throws SQLException
+//	 */
+//	private Map<String, String> getEmTdwgMap(Source source) throws SQLException {
+//
+//		Map<String, String> emTdwgMap = new HashMap<>();
+//		String sql = " SELECT EmCode, TDWGCode "
+//		    + " FROM emArea ";
+//		ResultSet rs = source.getResultSet(sql);
+//		while (rs.next()){
+//			String emCode = rs.getString("EMCode");
+//			String TDWGCode = rs.getString("TDWGCode");
+//			if (isNotBlank(emCode) ){
+//				emCode = emCode.trim();
+//				if (emCode.equalsIgnoreCase("Ab") || emCode.equalsIgnoreCase("Rf")||
+//						emCode.equalsIgnoreCase("Uk") || emCode.equalsIgnoreCase("Gg")
+//						|| emCode.equalsIgnoreCase("SM") || emCode.equalsIgnoreCase("Tu")){
+//					emTdwgMap.put(emCode, emCode);
+//				}else if (isNotBlank(TDWGCode)){
+//					emTdwgMap.put(emCode, TDWGCode.trim());
+//				}
+//			}
+//		}
+//		emTdwgMap.put("Ab / Ab(A)", "Ab");
+//		emTdwgMap.put("Ga / Ga(F)", "FRA-FR");
+//		emTdwgMap.put("It / It(I)", "ITA");
+//		emTdwgMap.put("Uk / Uk(U)", "Uk");
+//		emTdwgMap.put("Ar / Ar(A)", "TCS-AR");
+//		emTdwgMap.put("Hs / Hs(S)", "SPA-SP");
+//		emTdwgMap.put("Hb / Hb(E)", "IRE-IR");
+//
+//		return emTdwgMap;
+//	}
+
+
+
+    /**
+     * @param source
+     * @return
+     * @throws SQLException
+     */
+    private Map<String, NamedArea> getEmCodeToAreaMap(Source source) throws SQLException {
+        Map<String, NamedArea> emCodeToAreaMap = new HashMap<>();
+        String sql =
+              " SELECT EmCode, AreaId "
+            + " FROM emArea ";
+        ResultSet rs = source.getResultSet(sql);
+        while (rs.next()){
+
+            String emCode = rs.getString("EMCode");
+            if (isNotBlank(emCode)){
+                Integer areaId = rs.getInt("AreaId");
+                NamedArea area = getAreaByAreaId(areaId);
+                if (area != null){
+                    emCodeToAreaMap.put(emCode.trim(), area);
+                }else{
+                    logger.warn("Area not found for areaId " + areaId);
+                }
+            }
+
+        }
+
+//        emTdwgMap.put("Ab / Ab(A)", "Ab");
+
+        return emCodeToAreaMap;
+    }
+
+    /**
+     * @param emCode
+     * @return
+     */
+    private NamedArea getAreaByAreaId(int areaId) {
+        NamedArea result = null;
+        String areaIdStr = String.valueOf(areaId);
+        OrderedTermVocabulary<NamedArea> voc = getAreaVoc();
+        getVocabularyService().update(voc);
+        for (NamedArea area : voc.getTerms()){
+            for (IdentifiableSource source : area.getSources()){
+                if (areaIdStr.equals(source.getIdInSource()) && BerlinModelAreaImport.NAMESPACE.equals(source.getIdNamespace())){
+                    if (result != null){
+                        logger.warn("Result for areaId already exists. areaId: " + areaId);
+                    }
+                    result = area;
+                }
+            }
+        }
+        return result;
+    }
+
+    private OrderedTermVocabulary<NamedArea> areaVoc;
+    @SuppressWarnings("unchecked")
+    private OrderedTermVocabulary<NamedArea> getAreaVoc(){
+        if (areaVoc == null){
+            areaVoc = (OrderedTermVocabulary<NamedArea>)getVocabularyService().find(BerlinModelTransformer.uuidVocEuroMedAreas);
+        }
+        return areaVoc;
+    }
 
 
 	/**
@@ -739,7 +781,7 @@ public class BerlinModelCommonNamesImport  extends BerlinModelImportBase {
 			result.put(nameSpace, referenceMap);
 			// TODO remove if problem with duplicate DescElement_Annot id is solved
 		} catch (SQLException e) {
-			throw new RuntimeException("pos: " +pos, e);
+			throw new RuntimeException("pos: " + pos, e);
 		} catch (NullPointerException nep){
 			logger.error("NullPointerException in getRelatedObjectsForPartition()");
 		}
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportBase.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportBase.java
index ebf0e17f..07dedcce 100644
--- a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportBase.java
+++ b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportBase.java
@@ -287,7 +287,6 @@ public abstract class BerlinModelImportBase
 		}else if("TCS-AB;TCS-AD;TCS-GR".equals(tdwg)){
 			return Country.GEORGIA();
 
-
 		}else if("Cc".equals(em)){
 			return getNamedArea(state, BerlinModelTransformer.uuidCaucasia, "Caucasia (Ab + Ar + Gg + Rf(CS))", "Euro+Med area 'Caucasia (Ab + Ar + Gg + Rf(CS))'", "Cc", null, null);
 		}
@@ -394,4 +393,17 @@ public abstract class BerlinModelImportBase
         return markerTypeVoc;
     }
 
+
+    /**
+     * @param sourceReference
+     * @return
+     */
+    protected Reference getSourceReference(Reference sourceReference) {
+        Reference persistentSourceReference = getReferenceService().find(sourceReference.getUuid());  //just to be sure
+        if (persistentSourceReference != null){
+            sourceReference = persistentSourceReference;
+        }
+        return sourceReference;
+    }
+
 }
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportConfigurator.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportConfigurator.java
index 6173521d..e093f77d 100644
--- a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportConfigurator.java
+++ b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelImportConfigurator.java
@@ -139,12 +139,14 @@ public class BerlinModelImportConfigurator extends DbImportConfiguratorBase<Berl
 				, BerlinModelTypesImport.class
 				, BerlinModelTaxonImport.class
 				, BerlinModelFactsImport.class
-				, BerlinModelCommonNamesImport.class
+				, BerlinModelAreaImport.class
 				, BerlinModelOccurrenceImport.class
 				, BerlinModelOccurrenceSourceImport.class
 				, BerlinModelWebMarkerCategoryImport.class
 				, BerlinModelWebMarkerImport.class
 				, BerlinModelTaxonRelationImport.class
+                , BerlinModelCommonNamesImport.class
+
 		};
 	}
 
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelOccurrenceImport.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelOccurrenceImport.java
index 0db9bc80..4158ee3e 100644
--- a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelOccurrenceImport.java
+++ b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/BerlinModelOccurrenceImport.java
@@ -9,7 +9,6 @@
 
 package eu.etaxonomy.cdm.io.berlinModel.in;
 
-import java.net.URI;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.util.ArrayList;
@@ -18,40 +17,31 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
-import org.springframework.transaction.TransactionStatus;
 
 import eu.etaxonomy.cdm.common.CdmUtils;
 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
 import eu.etaxonomy.cdm.io.berlinModel.BerlinModelTransformer;
 import eu.etaxonomy.cdm.io.berlinModel.in.validation.BerlinModelOccurrenceImportValidator;
-import eu.etaxonomy.cdm.io.common.CdmImportBase;
 import eu.etaxonomy.cdm.io.common.IOValidator;
 import eu.etaxonomy.cdm.io.common.ResultSetPartitioner;
-import eu.etaxonomy.cdm.io.common.Source;
 import eu.etaxonomy.cdm.io.common.TdwgAreaProvider;
 import eu.etaxonomy.cdm.model.common.Annotation;
 import eu.etaxonomy.cdm.model.common.AnnotationType;
 import eu.etaxonomy.cdm.model.common.CdmBase;
-import eu.etaxonomy.cdm.model.common.ExtensionType;
+import eu.etaxonomy.cdm.model.common.IdentifiableSource;
 import eu.etaxonomy.cdm.model.common.Language;
 import eu.etaxonomy.cdm.model.common.Marker;
 import eu.etaxonomy.cdm.model.common.MarkerType;
 import eu.etaxonomy.cdm.model.common.OrderedTermVocabulary;
-import eu.etaxonomy.cdm.model.common.OriginalSourceType;
-import eu.etaxonomy.cdm.model.common.TermType;
-import eu.etaxonomy.cdm.model.common.TermVocabulary;
 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
 import eu.etaxonomy.cdm.model.description.Distribution;
 import eu.etaxonomy.cdm.model.description.PresenceAbsenceTerm;
 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.reference.Reference;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
@@ -64,7 +54,10 @@ import eu.etaxonomy.cdm.strategy.exceptions.UnknownCdmTypeException;
  */
 @Component
 public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
-	private static final Logger logger = Logger.getLogger(BerlinModelOccurrenceImport.class);
+
+    private static final long serialVersionUID = -7918122767284077183L;
+
+    private static final Logger logger = Logger.getLogger(BerlinModelOccurrenceImport.class);
 
 	public static final String NAMESPACE = "Occurrence";
 	private static final String EM_AREA_NAMESPACE = "emArea";
@@ -104,287 +97,55 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 		return strQuery;
 	}
 
-	private Map<Integer, NamedArea> euroMedAreas = new HashMap<Integer, NamedArea>();
+//	private Map<Integer, NamedArea> euroMedAreas = new HashMap<>();
 
 
 	@Override
 	public void doInvoke(BerlinModelImportState state) {
-		if (state.getConfig().isUseEmAreaVocabulary()){
-			try {
-				createEuroMedAreas(state);
-			} catch (Exception e) {
-				logger.error("Exception occurred when trying to create euroMed Areas");
-				e.printStackTrace();
-				state.setSuccess(false);
-			}
-		}
+//		if (state.getConfig().isUseEmAreaVocabulary()){
+//			try {
+//				createEuroMedAreas(state);
+//			} catch (Exception e) {
+//				logger.error("Exception occurred when trying to create euroMed Areas");
+//				e.printStackTrace();
+//				state.setSuccess(false);
+//			}
+//		}
 		super.doInvoke(state);
 		//reset
-		euroMedAreas = new HashMap<Integer, NamedArea>();
+//		euroMedAreas = new HashMap<>();
 	}
 
-	private TermVocabulary<NamedArea> createEuroMedAreas(BerlinModelImportState state) throws SQLException {
-		logger.warn("Start creating E+M areas");
-		Source source = state.getConfig().getSource();
-		Reference sourceReference = state.getConfig().getSourceReference();
-
-		TransactionStatus txStatus = this.startTransaction();
-
-		sourceReference = getSourceReference(sourceReference);
-
-		TermVocabulary<NamedArea> euroMedAreas = makeEmptyEuroMedVocabulary();
-
-		MarkerType eurMarkerType = getMarkerType(state, BerlinModelTransformer.uuidEurArea, "eur", "eur Area", "eur", getEuroMedMarkerTypeVoc());
-		MarkerType euroMedAreaMarkerType = getMarkerType(state, BerlinModelTransformer.uuidEurMedArea, "EuroMedArea", "EuroMedArea", "EuroMedArea", getEuroMedMarkerTypeVoc());
-		ExtensionType isoCodeExtType = getExtensionType(state, BerlinModelTransformer.uuidIsoCode, "IsoCode", "IsoCode", "iso");
-		ExtensionType tdwgCodeExtType = getExtensionType(state, BerlinModelTransformer.uuidTdwgAreaCode, "TDWG code", "TDWG Area code", "tdwg");
-		ExtensionType mclCodeExtType = getExtensionType(state, BerlinModelTransformer.uuidMclCode, "MCL code", "MedCheckList code", "mcl");
-		NamedAreaLevel areaLevelTop = getNamedAreaLevel(state, BerlinModelTransformer.uuidEuroMedAreaLevelTop, "Euro+Med top area level", "Euro+Med top area level. This level is only to be used for the area representing the complete Euro+Med area", "e+m top", null);
-		NamedAreaLevel areaLevelEm1 = getNamedAreaLevel(state, BerlinModelTransformer.uuidEuroMedAreaLevelFirst, "Euro+Med 1. area level", "Euro+Med 1. area level", "e+m 1.", null);
-		NamedAreaLevel areaLevelEm2 = getNamedAreaLevel(state, BerlinModelTransformer.uuidEuroMedAreaLevelSecond, "Euro+Med 2. area level", "Euro+Med 2. area level", "Euro+Med 1. area level", null);
-
-
-		String sql = "SELECT * , CASE WHEN EMCode = 'EM' THEN 'a' ELSE 'b' END as isEM " +
-				" FROM emArea " +
-				" ORDER BY isEM, EMCode";
-		ResultSet rs = source.getResultSet(sql);
-
-		NamedArea euroMedArea = null;
-		NamedArea lastLevel1Area = null;
-
-		//euroMedArea (EMCode = 'EM')
-		rs.next();
-		euroMedArea = makeSingleEuroMedArea(rs, eurMarkerType, euroMedAreaMarkerType, isoCodeExtType, tdwgCodeExtType, mclCodeExtType,
-				areaLevelTop, areaLevelEm1 , areaLevelEm2, sourceReference, euroMedArea, lastLevel1Area);
-		euroMedAreas.addTerm(euroMedArea);
-
-		//all other areas
-		while (rs.next()){
-			NamedArea newArea = makeSingleEuroMedArea(rs, eurMarkerType, euroMedAreaMarkerType,
-					isoCodeExtType, tdwgCodeExtType, mclCodeExtType,
-					areaLevelTop, areaLevelEm1 , areaLevelEm2, sourceReference, euroMedArea, lastLevel1Area);
-			if (newArea != null){
-    			euroMedAreas.addTerm(newArea);
-    			if (newArea.getPartOf().equals(euroMedArea)){
-    				lastLevel1Area = newArea;
-    			}
-			}
-		}
-		emAreaFinetuning(euroMedAreas, areaLevelEm2);
-
-		markAreasAsHidden(state, euroMedAreas);
-
-	    getVocabularyService().saveOrUpdate(euroMedAreas);
-
-		try {
-            commitTransaction(txStatus);
-        } catch (Exception e) {
-             e.printStackTrace();
-             logger.error("An exception occurred when trying to commit E+M Areas");
-        }
-		logger.warn("Created E+M areas");
-
-		return euroMedAreas;
-	}
-
-	/**
-     * @param areaLevelEm2
-	 * @param euroMedAreas2
+    /**
+     * @param emCode
+     * @return
      */
-    private void emAreaFinetuning(TermVocabulary<NamedArea> euroMedAreas, NamedAreaLevel areaLevelEm2) {
-        //CZ
-        NamedArea oldArea = euroMedAreas.getTermByIdInvocabulary("Cz");
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Cs"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sk"), areaLevelEm2);
-
-        //Ju
-        oldArea = euroMedAreas.getTermByIdInvocabulary("Ju");
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("BH"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Cg"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Ct"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Mk"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sl"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sr"), areaLevelEm2);
-
-        //IJ
-        oldArea = euroMedAreas.getTermByIdInvocabulary("IJ");
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Ir"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Jo"), areaLevelEm2);
-
-        //LS
-        oldArea = euroMedAreas.getTermByIdInvocabulary("LS");
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Le"), areaLevelEm2);
-        makeSubterm(oldArea, euroMedAreas.getTermByIdInvocabulary("Sy"), areaLevelEm2);
-
-    }
-
-    //5.Mark areas to be hidden #3979 .5
-    private void markAreasAsHidden(BerlinModelImportState state, TermVocabulary<NamedArea> euroMedAreasVoc) {
-
-        try {
-
-            @SuppressWarnings("unchecked")
-            TermVocabulary<MarkerType> vocUserDefinedMarkerTypes = getVocabularyService().find(CdmImportBase.uuidUserDefinedMarkerTypeVocabulary);
-            if (vocUserDefinedMarkerTypes == null){
-                String message = "Marker type vocabulary could not be found. Hidden areas not added.";
-                logger.error(message);
-                System.out.println(message);
+    private NamedArea getAreaByAreaId(int areaId) {
+        NamedArea result = null;
+        String areaIdStr = String.valueOf(areaId);
+        OrderedTermVocabulary<NamedArea> voc = getAreaVoc();
+        for (NamedArea area : voc.getTerms()){
+            for (IdentifiableSource source : area.getSources()){
+                if (areaIdStr.equals(source.getIdInSource()) && BerlinModelAreaImport.NAMESPACE.equals(source.getIdNamespace())){
+                    if (result != null){
+                        logger.warn("Result for areaId already exists. areaId: " + areaId);
+                    }
+                    result = area;
+                }
             }
-            MarkerType hiddenAreaMarkerType = getMarkerType(state, BerlinModelTransformer.uuidHiddenArea,
-                    "Hidden Area","Used to hide distributions for the named areas in publications", null, getEuroMedMarkerTypeVoc());
-
-            //Add hidden area marker to Rs(C) and Rs(N)
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs);
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_B);
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_C);
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_E);
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_N);
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_K);
-            hideArea(euroMedAreasVoc, hiddenAreaMarkerType, BerlinModelTransformer.uuidRs_W);
-        } catch (Exception e) {
-            e.printStackTrace();
-            logger.error("Exception in markAreasAsHidden: " + e.getMessage());
         }
-
+        return result;
     }
 
-    private void hideArea(TermVocabulary<NamedArea> euroMedAreasVoc, MarkerType hiddenAreaMarkerType, UUID areaUuid) {
-        for (NamedArea namedArea : euroMedAreasVoc){
-            if (namedArea.getUuid().equals(areaUuid)){
-                namedArea.addMarker(Marker.NewInstance(hiddenAreaMarkerType, true));
-                return;
-            }
+    private OrderedTermVocabulary<NamedArea> areaVoc;
+    @SuppressWarnings("unchecked")
+    private OrderedTermVocabulary<NamedArea> getAreaVoc(){
+        if (areaVoc == null){
+            areaVoc = (OrderedTermVocabulary<NamedArea>)getVocabularyService().find(BerlinModelTransformer.uuidVocEuroMedAreas);
         }
+        return areaVoc;
     }
 
-    /**
-     * @param oldArea
-     * @param namedArea
-     * @param areaLevelEm2
-     */
-    private void makeSubterm(NamedArea oldArea, NamedArea namedArea, NamedAreaLevel areaLevelEm2) {
-        namedArea.setLevel(areaLevelEm2);
-        namedArea.setPartOf(oldArea);
-    }
-
-    /**
-	 * @param sourceReference
-	 * @return
-	 */
-	private Reference getSourceReference(Reference sourceReference) {
-		Reference persistentSourceReference = getReferenceService().find(sourceReference.getUuid());  //just to be sure
-		if (persistentSourceReference != null){
-			sourceReference = persistentSourceReference;
-		}
-		return sourceReference;
-	}
-
-	/**
-	 * @param eurMarkerType
-	 * @param euroMedAreaMarkerType
-	 * @param isoCodeExtType
-	 * @param tdwgCodeExtType
-	 * @param mclCodeExtType
-	 * @param rs
-	 * @param areaLevelEm2
-	 * @param areaLevelEm1
-	 * @param areaLevelTop
-	 * @throws SQLException
-	 */
-	private NamedArea makeSingleEuroMedArea(ResultSet rs, MarkerType eurMarkerType,
-			MarkerType euroMedAreaMarkerType, ExtensionType isoCodeExtType,
-			ExtensionType tdwgCodeExtType, ExtensionType mclCodeExtType,
-			NamedAreaLevel areaLevelTop, NamedAreaLevel areaLevelEm1, NamedAreaLevel areaLevelEm2,
-			Reference sourceReference, NamedArea euroMedArea, NamedArea level1Area) throws SQLException {
-		Integer areaId = rs.getInt("AreaId");
-		String emCode = nullSafeTrim(rs.getString("EMCode"));
-		String isoCode = nullSafeTrim(rs.getString("ISOCode"));
-		String tdwgCode = nullSafeTrim(rs.getString("TDWGCode"));
-		String unit = nullSafeTrim(rs.getString("Unit"));
-//				      ,[Status]
-//				      ,[OutputOrder]
-		boolean eurMarker = rs.getBoolean("eur");
-		boolean euroMedAreaMarker = rs.getBoolean("EuroMedArea");
-		String notes = nullSafeTrim(rs.getString("Notes"));
-		String mclCode = nullSafeTrim(rs.getString("MCLCode"));
-		String geoSearch = nullSafeTrim(rs.getString("NameForGeoSearch"));
-
-
-
-		if (isBlank(emCode)){
-			emCode = unit;
-		}
-
-		//uuid
-		UUID uuid = BerlinModelTransformer.getEMAreaUuid(emCode);
-		NamedArea area = (NamedArea)getTermService().find(uuid);
-		if (area == null){
-			//label
-			area = NamedArea.NewInstance(geoSearch, unit, emCode);
-			if (uuid != null){
-				area.setUuid(uuid);
-			}else{
-			    if (areaId == 211 || areaId == 213){  //Additional Azores and Canary Is. area are merged into primary area, see also area.addSource part below
-			        return null;
-			    }
-				logger.warn("Uuid for emCode could not be defined: " + emCode);
-			}
-		}
-
-
-		//code
-		area.setIdInVocabulary(emCode);
-		//notes
-		if (StringUtils.isNotEmpty(notes)){
-			area.addAnnotation(Annotation.NewInstance(notes, AnnotationType.EDITORIAL(), Language.DEFAULT()));
-		}
-		//markers
-		area.addMarker(Marker.NewInstance(eurMarkerType, eurMarker));
-		area.addMarker(Marker.NewInstance(euroMedAreaMarkerType, euroMedAreaMarker));
-
-		//extensions
-		if (isNotBlank(isoCode)){
-			area.addExtension(isoCode, isoCodeExtType);
-		}
-		if (isNotBlank(tdwgCode)){
-			area.addExtension(tdwgCode, tdwgCodeExtType);
-		}
-		if (isNotBlank(mclCode)){
-			area.addExtension(mclCode, mclCodeExtType);
-		}
-
-		//type
-		area.setType(NamedAreaType.ADMINISTRATION_AREA());
-
-		//source
-		area.addSource(OriginalSourceType.Import, String.valueOf(areaId), EM_AREA_NAMESPACE, sourceReference, null);
-		//add duplicate area ids for canary
-		if (areaId == 624){ //Canary Is.
-		    area.addSource(OriginalSourceType.Import, String.valueOf(213), EM_AREA_NAMESPACE, sourceReference, null);
-		}
-		if (areaId == 210){//Azores
-            area.addSource(OriginalSourceType.Import, String.valueOf(211), EM_AREA_NAMESPACE, sourceReference, null);
-        }
-
-		//parent
-		if (euroMedArea != null){
-			if (emCode.contains("(")){
-				area.setPartOf(level1Area);
-				area.setLevel(areaLevelEm2);
-			}else{
-				area.setPartOf(euroMedArea);
-				area.setLevel(areaLevelEm1);
-			}
-		}else{
-			area.setLevel(areaLevelTop);
-		}
-		this.euroMedAreas.put(areaId, area);
-
-		//save
-		getTermService().saveOrUpdate(area);
-
-		return area;
-	}
 
 	private String nullSafeTrim(String string) {
 		if (string == null){
@@ -394,26 +155,10 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 		}
 	}
 
-	/**
-	 *
-	 */
-	private TermVocabulary<NamedArea> makeEmptyEuroMedVocabulary() {
-		TermType type = TermType.NamedArea;
-		String description = "Euro+Med area vocabulary";
-		String label = "E+M areas";
-		String abbrev = null;
-		URI termSourceUri = null;
-		OrderedTermVocabulary<NamedArea> result = OrderedTermVocabulary.NewInstance(type, description, label, abbrev, termSourceUri);
-
-		result.setUuid(BerlinModelTransformer.uuidVocEuroMedAreas);
-		getVocabularyService().save(result);
-		return result;
-	}
-
 	@Override
 	public boolean doPartition(ResultSetPartitioner partitioner, BerlinModelImportState state) {
 		boolean success = true;
-		Set<TaxonBase> taxaToSave = new HashSet<TaxonBase>();
+		Set<TaxonBase> taxaToSave = new HashSet<>();
 
 		Map<String, TaxonBase<?>> taxonMap = partitioner.getObjectMap(BerlinModelTaxonImport.NAMESPACE);
 
@@ -422,7 +167,7 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 		try {
 			//map to store the mapping of duplicate berlin model occurrences to their real distributions
 			//duplicated may occur due to area mappings from BM areas to TDWG areas
-			Map<Integer, String> duplicateMap = new HashMap<Integer, String>();
+			Map<Integer, String> duplicateMap = new HashMap<>();
 			int oldTaxonId = -1;
 			TaxonDescription oldDescription = null;
 			int i = 0;
@@ -453,7 +198,7 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 
 					Reference sourceRef = state.getTransactionalSourceReference();
 
-					List<NamedArea> areas = makeAreaList(state, rs,	occurrenceId);
+					List<NamedArea> areas = makeAreaList(state, partitioner, rs, occurrenceId);
 
                     //create description(elements)
                     TaxonDescription taxonDescription = getTaxonDescription(newTaxonId, oldTaxonId, oldDescription, taxonMap, occurrenceId, sourceRef);
@@ -513,6 +258,7 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 
 	/**
 	 * @param state
+	 * @param partitioner
 	 * @param rs
 	 * @param occurrenceId
 	 * @param tdwgCodeString
@@ -521,12 +267,16 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 	 * @throws SQLException
 	 */
 	//Create area list
-	private List<NamedArea> makeAreaList(BerlinModelImportState state, ResultSet rs, int occurrenceId) throws SQLException {
-		List<NamedArea> areas = new ArrayList<NamedArea>();
+	private List<NamedArea> makeAreaList(BerlinModelImportState state, ResultSetPartitioner partitioner, ResultSet rs, int occurrenceId) throws SQLException {
+
+	    List<NamedArea> areas = new ArrayList<>();
 
 		if (state.getConfig().isUseEmAreaVocabulary()){
-			Integer areaId = rs.getInt("AreaId");
-	        NamedArea area = this.euroMedAreas.get(areaId);
+		    Integer areaId = rs.getInt("AreaId");
+			NamedArea area = getAreaByAreaId(areaId);
+			if (area == null){
+			    logger.warn("Area for areaId " + areaId + " not found.");
+			}
 			areas.add(area);
 		}else{
 	        String tdwgCodeString = rs.getString("TDWGCode");
@@ -566,32 +316,29 @@ public class BerlinModelOccurrenceImport  extends BerlinModelImportBase {
 
 	@Override
 	public Map<Object, Map<String, ? extends CdmBase>> getRelatedObjectsForPartition(ResultSet rs, BerlinModelImportState state) {
-		String nameSpace;
-		Class<?> cdmClass;
-		Set<String> idSet;
-		Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<Object, Map<String, ? extends CdmBase>>();
 
 		try{
+
+		    Map<Object, Map<String, ? extends CdmBase>> result = new HashMap<>();
 			Set<String> taxonIdSet = new HashSet<String>();
 			while (rs.next()){
 				handleForeignKey(rs, taxonIdSet, "taxonId");
 			}
 
 			//taxon map
-			nameSpace = BerlinModelTaxonImport.NAMESPACE;
-			cdmClass = TaxonBase.class;
-			idSet = taxonIdSet;
-			Map<String, TaxonBase> objectMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
+			String nameSpace = BerlinModelTaxonImport.NAMESPACE;
+			Class<?> cdmClass = TaxonBase.class;
+			Set<String> idSet = taxonIdSet;
+			Map<String, ? extends CdmBase> objectMap = (Map<String, TaxonBase>)getCommonService().getSourcedObjectsByIdInSource(cdmClass, idSet, nameSpace);
 			result.put(nameSpace, objectMap);
 
+			return result;
 		} catch (SQLException e) {
 			throw new RuntimeException(e);
 		}
-		return result;
 	}
 
 
-
 	/**
      * Tests if a distribution with the same tdwgArea and the same status already exists in the description.
      * If so the old distribution is returned
diff --git a/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/validation/BerlinModelAreaImportValidator.java b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/validation/BerlinModelAreaImportValidator.java
new file mode 100644
index 00000000..f0b1c9d2
--- /dev/null
+++ b/app-import/src/main/java/eu/etaxonomy/cdm/io/berlinModel/in/validation/BerlinModelAreaImportValidator.java
@@ -0,0 +1,73 @@
+/**
+* Copyright (C) 2007 EDIT
+* European Distributed Institute of Taxonomy
+* http://www.e-taxonomy.eu
+*
+* The contents of this file are subject to the Mozilla Public License Version 1.1
+* See LICENSE.TXT at the top of this package for the full license terms.
+*/
+
+package eu.etaxonomy.cdm.io.berlinModel.in.validation;
+
+import org.apache.log4j.Logger;
+
+import eu.etaxonomy.cdm.io.berlinModel.in.BerlinModelImportState;
+import eu.etaxonomy.cdm.io.common.IOValidator;
+
+/**
+ * @author a.mueller
+ * @since 17.02.2010
+ */
+public class BerlinModelAreaImportValidator implements IOValidator<BerlinModelImportState> {
+	@SuppressWarnings("unused")
+    private static final Logger logger = Logger.getLogger(BerlinModelAreaImportValidator.class);
+
+	@Override
+	public boolean validate(BerlinModelImportState state) {
+		boolean result = true;
+//		BerlinModelImportConfigurator config = state.getConfig();
+//		result &= checkSourcesWithWhitespace(config);
+		return result;
+	}
+
+
+	//******************************** CHECK *************************************************
+
+
+//    private static boolean checkSourcesWithWhitespace(BerlinModelImportConfigurator config){
+//        try {
+//            boolean result = true;
+//            Source source = config.getSource();
+//            String strSelect = "SELECT OccurrenceId, PTNameFk, PTRefFk, AreaFk, Sources, Created_When, Created_Who, Updated_When, Updated_Who, Notes, Occurrence ";
+//            String strCount = " SELECT count(*) as n";
+//            String strQueryBase =
+//                    " FROM emOccurrence " +
+//                    " WHERE (Sources LIKE '%  %') OR (Sources LIKE '% ') OR (Sources LIKE ' %') ";
+//
+//            ResultSet rs = source.getResultSet(strCount + strQueryBase);
+//            rs.next();
+//            int n = rs.getInt("n");
+//            if (n > 0){
+//                System.out.println("=======================================================================");
+//                System.out.println("There are "+n+" occurrences with source attribute has unexpected whitespace!");
+//                System.out.println("---------------------------------------------------------------");
+//                System.out.println(strSelect + strQueryBase);
+//                System.out.println("=======================================================================");
+//            }
+//
+//            rs = source.getResultSet(strSelect + strQueryBase);
+//            while (rs.next()){
+//                int occurrenceId = rs.getInt("OccurrenceId");
+//                String sources = rs.getString("Sources");
+//
+//                System.out.println("OccurrenceSourceId:" + occurrenceId +
+//                        "\n  Sources: " + sources)
+//                        ;
+//            }
+//            return result;
+//        } catch (SQLException e) {
+//            e.printStackTrace();
+//            return false;
+//        }
+//    }
+}
