@Override
  public void exportGroupRemoveInitiators(
      URI storageURI, URI exportGroupURI, List<URI> initiatorURIs, String token) throws Exception {
    /*
     * foreach ScaleOI volume in ExportGroup
     * foreach initiator in list
     * if volume not used in another ExportGroup with same initiator
     * scli unmap --volume volid --sdc initiator.sdcid
     */
    ExportOrchestrationTask taskCompleter = new ExportOrchestrationTask(exportGroupURI, token);
    try {
      ExportGroup exportGroup = _dbClient.queryObject(ExportGroup.class, exportGroupURI);
      StorageSystem storage = _dbClient.queryObject(StorageSystem.class, storageURI);

      if (initiatorURIs != null
          && !initiatorURIs.isEmpty()
          && exportGroup.getExportMasks() != null) {
        // Set up workflow steps.
        Workflow workflow =
            _workflowService.getNewWorkflow(
                MaskingWorkflowEntryPoints.getInstance(),
                "exportGroupRemoveInitiators",
                true,
                token);

        // Create a mapping of ExportMask URI to initiators to remove
        Map<URI, List<URI>> exportToInitiatorsToRemove = new HashMap<>();
        Map<URI, List<URI>> exportToVolumesToRemove = new HashMap<>();
        Map<URI, Integer> volumeMap = null;
        for (String exportMaskURIStr : exportGroup.getExportMasks()) {
          URI exportMaskURI = URI.create(exportMaskURIStr);
          ExportMask exportMask = _dbClient.queryObject(ExportMask.class, exportMaskURI);
          if (exportMask == null) {
            continue;
          }
          for (URI initiatorURI : initiatorURIs) {
            Initiator initiator = _dbClient.queryObject(Initiator.class, initiatorURI);
            if (initiator == null || !exportMask.hasInitiator(initiatorURI.toString())) {
              continue;
            }
            if (ExportUtils.getInitiatorExportGroups(initiator, _dbClient).size() == 1) {
              List<URI> initiators = exportToInitiatorsToRemove.get(exportGroupURI);
              if (initiators == null) {
                initiators = new ArrayList<>();
                exportToInitiatorsToRemove.put(exportMaskURI, initiators);
              }
              initiators.add(initiatorURI);
            } else {
              if (volumeMap == null) {
                volumeMap = ExportUtils.getExportGroupVolumeMap(_dbClient, storage, exportGroup);
              }
              List<URI> volumeURIs = exportToVolumesToRemove.get(exportGroupURI);
              if (volumeURIs == null) {
                volumeURIs = new ArrayList<>();
                exportToVolumesToRemove.put(exportMaskURI, volumeURIs);
              }
              for (URI volumeURI : volumeMap.keySet()) {
                // Only add to the remove list for the ExportMask if
                // the EM is not being shared with another ExportGroup
                Integer count =
                    ExportUtils.getNumberOfExportGroupsWithVolume(initiator, volumeURI, _dbClient);
                if (count == 1) {
                  volumeURIs.add(volumeURI);
                }
              }
            }
          }
        }

        // Generate the remove initiators steps for the entries that were determined above
        for (Map.Entry<URI, List<URI>> toRemoveInits : exportToInitiatorsToRemove.entrySet()) {
          ExportMask exportMask = _dbClient.queryObject(ExportMask.class, toRemoveInits.getKey());
          if (exportMask != null) {
            List<URI> removeInitURIs = toRemoveInits.getValue();
            List<String> exportMaskInitiatorURIs = new ArrayList<>(exportMask.getInitiators());
            for (URI uri : removeInitURIs) {
              exportMaskInitiatorURIs.remove(uri.toString());
            }
            if (exportMaskInitiatorURIs.isEmpty()) {
              log.info(
                  String.format("Adding step to delete ExportMask %s", exportMask.getMaskName()));
              generateExportMaskDeleteWorkflow(
                  workflow, null, storage, exportGroup, exportMask, null);
            } else {
              log.info(
                  String.format(
                      "Adding step to remove initiators %s from ExportMask %s",
                      Joiner.on(',').join(removeInitURIs), exportMask.getMaskName()));
              generateExportMaskRemoveInitiatorsWorkflow(
                  workflow, null, storage, exportGroup, exportMask, removeInitURIs, true);
            }
          }
        }

        // Generate the remove volume for those cases where we remove initiators
        // from an ExportGroup that contains more than one host/initiator
        for (Map.Entry<URI, List<URI>> toRemoveVols : exportToVolumesToRemove.entrySet()) {
          ExportMask exportMask = _dbClient.queryObject(ExportMask.class, toRemoveVols.getKey());
          List<URI> removeVolumeURIs = toRemoveVols.getValue();
          if (exportMask != null && !removeVolumeURIs.isEmpty()) {
            List<String> exportMaskVolumeURIs = new ArrayList<>(exportMask.getVolumes().keySet());
            for (URI uri : removeVolumeURIs) {
              exportMaskVolumeURIs.remove(uri.toString());
            }
            if (exportMaskVolumeURIs.isEmpty()) {
              log.info(
                  String.format("Adding step to delete ExportMask %s", exportMask.getMaskName()));
              generateExportMaskDeleteWorkflow(
                  workflow, null, storage, exportGroup, exportMask, null);
            } else {
              log.info(
                  String.format(
                      "Adding step to remove volumes %s from ExportMask %s",
                      Joiner.on(',').join(removeVolumeURIs), exportMask.getMaskName()));
              generateExportMaskRemoveVolumesWorkflow(
                  workflow, null, storage, exportGroup, exportMask, removeVolumeURIs, null);
            }
          }
        }

        String successMessage =
            String.format(
                "ExportGroup remove initiators successfully applied for StorageArray %s",
                storage.getLabel());
        workflow.executePlan(taskCompleter, successMessage);
      } else {
        taskCompleter.ready(_dbClient);
      }
    } catch (DeviceControllerException dex) {
      taskCompleter.error(
          _dbClient,
          DeviceControllerErrors.scaleio.encounteredAnExceptionFromScaleIOOperation(
              "exportGroupRemoveInitiators", dex.getMessage()));
    } catch (Exception ex) {
      _log.error("ExportGroup Orchestration failed.", ex);
      taskCompleter.error(
          _dbClient,
          DeviceControllerErrors.scaleio.encounteredAnExceptionFromScaleIOOperation(
              "exportGroupRemoveInitiators", ex.getMessage()));
    }
  }