class DistCpOptionsParser {

  protected DistCpOptions parse(Map<String, Object> copierOptions) {
    if (copierOptions == null) {
      LOG.debug("Null copier options: nothing to parse");
      return distCpOptions;
    }

    List<FileAttribute> fileAttributes = MoreMapUtils.getListOfEnum(copierOptions, FILE_ATTRIBUTES,
        Collections.<FileAttribute>emptyList(), FileAttribute.class);
    for (FileAttribute fileAttribute : fileAttributes) {
      distCpOptions.preserve(fileAttribute);
    }
    if (MapUtils.getBoolean(copierOptions, PRESERVE_RAW_XATTRS, distCpOptions.shouldPreserveRawXattrs())) {
      distCpOptions.preserveRawXattrs();
    }
    distCpOptions.setAtomicWorkPath(
        MoreMapUtils.getHadoopPath(copierOptions, ATOMIC_WORK_PATH, distCpOptions.getAtomicWorkPath()));
    distCpOptions.setCopyStrategy(MapUtils.getString(copierOptions, COPY_STRATEGY, distCpOptions.getCopyStrategy()));
    distCpOptions
        .setIgnoreFailures(MapUtils.getBoolean(copierOptions, IGNORE_FAILURES, distCpOptions.shouldIgnoreFailures()));
    distCpOptions.setLogPath(MoreMapUtils.getHadoopPath(copierOptions, LOG_PATH, distCpOptions.getLogPath()));

    int taskBandwidth = MapUtils.getIntValue(copierOptions, TASK_BANDWIDTH, distCpOptions.getMapBandwidth());
    if (taskBandwidth <= 0) {
      throw new IllegalArgumentException("Parameter " + TASK_BANDWIDTH + " must be a positive integer.");
    }
    distCpOptions.setMapBandwidth(taskBandwidth);

    int maxMaps = MapUtils.getIntValue(copierOptions, MAX_MAPS, distCpOptions.getMaxMaps());
    if (maxMaps <= 0) {
      throw new IllegalArgumentException("Parameter " + MAX_MAPS + " must be a positive integer.");
    }
    distCpOptions.setMaxMaps(maxMaps);

    distCpOptions.setSslConfigurationFile(
        MapUtils.getString(copierOptions, SSL_CONFIGURATION_FILE, distCpOptions.getSslConfigurationFile()));
    // These validate: order is important
    distCpOptions
        .setAtomicCommit(MapUtils.getBoolean(copierOptions, ATOMIC_COMMIT, distCpOptions.shouldAtomicCommit()));
    distCpOptions.setSkipCRC(MapUtils.getBoolean(copierOptions, SKIP_CRC, distCpOptions.shouldSkipCRC()));
    return distCpOptions;
  }

    DistCpOptionsParser(List<Path> sourceDataLocations, Path replicaDataLocation);

}