private InternalMapLayer getSingleInternalMapLayer(MapView mapView, User user, Date date) {
    if (mapView == null) {
      return null;
    }

    List<OrganisationUnit> atLevels = new ArrayList<OrganisationUnit>();
    List<OrganisationUnit> inGroups = new ArrayList<OrganisationUnit>();

    if (mapView.hasOrganisationUnitLevels()) {
      atLevels.addAll(
          organisationUnitService.getOrganisationUnitsAtLevels(
              mapView.getOrganisationUnitLevels(), mapView.getOrganisationUnits()));
    }

    if (mapView.hasItemOrganisationUnitGroups()) {
      inGroups.addAll(
          organisationUnitService.getOrganisationUnits(
              mapView.getItemOrganisationUnitGroups(), mapView.getOrganisationUnits()));
    }

    date = date != null ? date : new Date();

    mapView.init(user, date, null, atLevels, inGroups, null);

    List<OrganisationUnit> organisationUnits = mapView.getAllOrganisationUnits();

    FilterUtils.filter(organisationUnits, new OrganisationUnitWithCoordinatesFilter());

    java.util.Map<String, OrganisationUnit> uidOuMap = new HashMap<String, OrganisationUnit>();

    for (OrganisationUnit ou : organisationUnits) {
      uidOuMap.put(ou.getUid(), ou);
    }

    String name = mapView.getName();

    Period period = null;

    if (!mapView.getPeriods().isEmpty()) // TODO integrate with BaseAnalyticalObject
    {
      period = mapView.getPeriods().get(0);
    } else if (mapView.getRelatives() != null) {
      period = mapView.getRelatives().getRelativePeriods(date, null, false).get(0);
    }

    Integer radiusLow =
        mapView.getRadiusLow() != null ? mapView.getRadiusLow() : DEFAULT_RADIUS_LOW;
    Integer radiusHigh =
        mapView.getRadiusHigh() != null ? mapView.getRadiusHigh() : DEFAULT_RADIUS_HIGH;

    // Get the low and high colors, typically in hexadecimal form, e.g. #ff3200
    Color colorLow =
        MapUtils.createColorFromString(
            StringUtils.trimToNull(mapView.getColorLow()) != null
                ? mapView.getColorLow()
                : DEFAULT_COLOR_LOW);
    Color colorHigh =
        MapUtils.createColorFromString(
            StringUtils.trimToNull(mapView.getColorHigh()) != null
                ? mapView.getColorHigh()
                : DEFAULT_COLOR_HIGH);

    Float opacity =
        mapView.getOpacity() != null ? mapView.getOpacity().floatValue() : DEFAULT_OPACITY;

    // TODO MapView should be extended to feature stroke color
    Color strokeColor = MapUtils.createColorFromString(DEFAULT_STROKE_COLOR);

    // TODO MapView might be extended to feature stroke width
    int strokeWidth = DEFAULT_STROKE_WIDTH;

    boolean hasLegendSet = mapView.hasLegendSet();

    // Create and setup an internal layer
    InternalMapLayer mapLayer = new InternalMapLayer();
    mapLayer.setName(name);
    mapLayer.setPeriod(period);
    mapLayer.setRadiusLow(radiusLow);
    mapLayer.setRadiusHigh(radiusHigh);
    mapLayer.setColorLow(colorLow);
    mapLayer.setColorHigh(colorHigh);
    mapLayer.setOpacity(opacity);
    mapLayer.setClasses(mapView.getClasses());
    mapLayer.setStrokeColor(strokeColor);
    mapLayer.setStrokeWidth(strokeWidth);

    if (!mapView.isDataLayer()) // Boundary (and facility) layer
    {
      for (OrganisationUnit unit : organisationUnits) {
        mapLayer.addBoundaryMapObject(unit);
      }
    } else // Thematic layer
    {
      Collection<MapValue> mapValues = getAggregatedMapValues(mapView);

      if (mapValues.isEmpty()) {
        return null;
      }

      // Build and set the internal GeoTools map objects for the layer

      for (MapValue mapValue : mapValues) {
        OrganisationUnit orgUnit = uidOuMap.get(mapValue.getOu());

        if (orgUnit != null) {
          mapLayer.addDataMapObject(mapValue.getValue(), orgUnit);
        }
      }

      if (!mapLayer.hasMapObjects()) {
        return null;
      }

      // Create an interval set for this map layer that distributes its map
      // objects into their respective intervals

      if (hasLegendSet) {
        mapLayer.setIntervalSetFromLegendSet(mapView.getLegendSet());
        mapLayer.distributeAndUpdateMapObjectsInIntervalSet();
      } else {
        mapLayer.setAutomaticIntervalSet(
            DistributionStrategy.STRATEGY_EQUAL_RANGE, mapLayer.getClasses());
        mapLayer.distributeAndUpdateMapObjectsInIntervalSet();
      }

      // Update the radius of each map object in this map layer according to
      // its map object's highest and lowest values

      mapLayer.applyInterpolatedRadii();
    }

    return mapLayer;
  }