static List<StorageAccountInfo> parseStorageAccountInfo(String storageAccountInfoStr) {
    if (storageAccountInfoStr.isEmpty()) {
      return Collections.emptyList();
    }
    int prev_partition_upper_bound = 0;
    List<StorageAccountInfo> storageAccountInfoList = new ArrayList<>();
    JSONObject root = new JSONObject(storageAccountInfoStr);
      JSONArray all = root.getJSONArray(AZURE_STORAGE_ACCOUNT_INFO_STR);
      for (int i = 0; i < all.length(); i++) {
        JSONObject entry = all.getJSONObject(i);
        String name = entry.optString(AZURE_STORAGE_ACCOUNT_INFO_NAME);
        if (name.isEmpty()) {
          throw new IllegalArgumentException(String.format("Storage account #%d is missing the name setting", i));
        }
        String storageScope = entry.optString(AZURE_STORAGE_ACCOUNT_INFO_STORAGE_SCOPE);
        String storageEndpoint = entry.optString(AZURE_STORAGE_ACCOUNT_INFO_STORAGE_ENDPOINT);
        String storageConnectionString = entry.optString(AZURE_STORAGE_ACCOUNT_INFO_STORAGE_CONNECTION_STRING);
        String partitionRange = entry.optString(AZURE_STORAGE_ACCOUNT_INFO_PARTITION_RANGE);
        if (partitionRange.isEmpty()) {
          throw new IllegalArgumentException(
              String.format("The partition range for the storage account %s is missing", name));
        }
        Pattern p = Pattern.compile("(\\d+)-(\\d+)");
        Matcher m = p.matcher(partitionRange);
        if (!m.find()) {
          throw new IllegalArgumentException(
              String.format("The partition range %s for the storage account %s is not valid", partitionRange, name));
        }
        final int lower_partition_bound = Integer.parseInt(m.group(1));
        final int upper_partition_bound = Integer.parseInt(m.group(2));

        if (upper_partition_bound - lower_partition_bound < 1) {
          throw new IllegalArgumentException(
              String.format("The partition range %s for the storage account %s is not valid", partitionRange, name));
        }

        if (lower_partition_bound != prev_partition_upper_bound) {
          throw new IllegalArgumentException(
              String.format("The partition range %s for the storage account %s is not valid since it leaves a "
              + "gap which is not covered by other storage accounts", partitionRange, name));
        }
        prev_partition_upper_bound = upper_partition_bound;
        storageAccountInfoList.add(new StorageAccountInfo(name, lower_partition_bound, upper_partition_bound,
            storageScope, storageEndpoint, storageConnectionString));
      }

      return storageAccountInfoList;
  }
Parse storage account info portion of the {@link AzureCloudConfig} and return the list of storage accounts
in the form of {@link StorageAccountInfo}.
@param storageAccountInfoStr list of storage account info in the form of json string.
@return the list of {@link StorageAccountInfo}.
ambry-cloud/src/main/java/com/github/ambry/cloud/azure/AzureCloudConfig.java