class S3MapReduceCpOptionsParser {

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

    optionsBuilder
        .credentialsProvider(MoreMapUtils.getUri(copierOptions, CREDENTIAL_PROVIDER, defaultCredentialsProvider));

    long multipartUploadPartSize = MapUtils.getLongValue(copierOptions, MULTIPART_UPLOAD_CHUNK_SIZE,
        ConfigurationVariable.MULTIPART_UPLOAD_THRESHOLD.defaultLongValue());
    if (multipartUploadPartSize <= 0) {
      throw new IllegalArgumentException("Parameter " + MULTIPART_UPLOAD_CHUNK_SIZE + " must be greater than zero");
    }
    optionsBuilder.multipartUploadPartSize(multipartUploadPartSize);

    optionsBuilder.s3ServerSideEncryption(MapUtils.getBoolean(copierOptions, S3_SERVER_SIDE_ENCRYPTION, true));

    optionsBuilder.storageClass(
        MapUtils.getString(copierOptions, STORAGE_CLASS, ConfigurationVariable.STORAGE_CLASS.defaultValue()));

    long maxBandwidth = MapUtils.getLongValue(copierOptions, TASK_BANDWIDTH,
        ConfigurationVariable.MAX_BANDWIDTH.defaultLongValue());
    if (maxBandwidth <= 0) {
      throw new IllegalArgumentException(
          "Parameter " + TASK_BANDWIDTH + " must be a positive number greater then zero");
    }
    optionsBuilder.maxBandwidth(maxBandwidth);

    int numberOfUploadWorkers = MapUtils.getIntValue(copierOptions, NUMBER_OF_WORKERS_PER_MAP,
        ConfigurationVariable.NUMBER_OF_UPLOAD_WORKERS.defaultIntValue());
    if (numberOfUploadWorkers <= 0) {
      throw new IllegalArgumentException(
          "Parameter " + NUMBER_OF_WORKERS_PER_MAP + " must be a positive number greater than zero");
    }
    optionsBuilder.numberOfUploadWorkers(numberOfUploadWorkers);

    long multipartUploadThreshold = MapUtils.getLongValue(copierOptions, MULTIPART_UPLOAD_THRESHOLD,
        ConfigurationVariable.MULTIPART_UPLOAD_THRESHOLD.defaultLongValue());
    if (multipartUploadThreshold <= 0) {
      throw new IllegalArgumentException("Parameter " + MULTIPART_UPLOAD_THRESHOLD + " must be greater than zero");
    }
    optionsBuilder.multipartUploadThreshold(multipartUploadThreshold);

    int maxMaps = MapUtils.getIntValue(copierOptions, MAX_MAPS, ConfigurationVariable.MAX_MAPS.defaultIntValue());
    if (maxMaps <= 0) {
      throw new IllegalArgumentException("Parameter " + MAX_MAPS + " must be a positive number greater than zero");
    }
    optionsBuilder.maxMaps(maxMaps);

    optionsBuilder.copyStrategy(
        MapUtils.getString(copierOptions, COPY_STRATEGY, ConfigurationVariable.COPY_STRATEGY.defaultValue()));

    Path logPath = MoreMapUtils.getHadoopPath(copierOptions, LOG_PATH, null);
    if (logPath != null) {
      optionsBuilder.logPath(logPath);
    }

    optionsBuilder.region(MapUtils.getString(copierOptions, REGION, ConfigurationVariable.REGION.defaultValue()));

    optionsBuilder.ignoreFailures(MapUtils.getBoolean(copierOptions, IGNORE_FAILURES,
        ConfigurationVariable.IGNORE_FAILURES.defaultBooleanValue()));

    optionsBuilder.s3EndpointUri(
        MoreMapUtils.getUri(copierOptions, S3_ENDPOINT_URI, ConfigurationVariable.S3_ENDPOINT_URI.defaultURIValue()));

    int uploadRetryCount = MapUtils.getInteger(copierOptions, UPLOAD_RETRY_COUNT,
        ConfigurationVariable.UPLOAD_RETRY_COUNT.defaultIntValue());
    if (uploadRetryCount < 0) {
      throw new IllegalArgumentException("Parameter " + UPLOAD_RETRY_COUNT + " must be a positive number");
    }
    optionsBuilder.uploadRetryCount(uploadRetryCount);

    long uploadRetryDelaysMs = MapUtils.getLong(copierOptions, UPLOAD_RETRY_DELAY_MS,
        ConfigurationVariable.UPLOAD_RETRY_DELAY_MS.defaultLongValue());
    optionsBuilder.uploadRetryDelayMs(uploadRetryDelaysMs);
    if (uploadRetryDelaysMs < 0) {
      throw new IllegalArgumentException("Parameter " + UPLOAD_RETRY_DELAY_MS + " must be a positive number");
    }

    int uploadBufferSize = MapUtils.getInteger(copierOptions, UPLOAD_BUFFER_SIZE,
        ConfigurationVariable.UPLOAD_BUFFER_SIZE.defaultIntValue());
    if (uploadBufferSize < 0) {
      throw new IllegalArgumentException("Parameter " + UPLOAD_BUFFER_SIZE + " must be a positive number");
    }
    optionsBuilder.uploadBufferSize(uploadBufferSize);

    optionsBuilder.cannedAcl(MapUtils.getString(copierOptions, CANNED_ACL, ConfigurationVariable.CANNED_ACL.defaultValue()));

    optionsBuilder.assumeRole(MapUtils.getString(copierOptions, ASSUME_ROLE, ConfigurationVariable.ASSUME_ROLE.defaultValue()));

    return optionsBuilder.build();
  }

    S3MapReduceCpOptionsParser(List<Path> sources, URI target, URI defaultCredentialsProvider);

}