fromFile static method

Future<Region> fromFile(
  1. String csvFile
)

Creates a Region instance by reading and parsing a CSV file.

The csvFile parameter is the full path to the region information CSV file.

Implementation

static Future<Region> fromFile(String csvFile) async {
  final region = Region._();

  final file = File(csvFile);
  if (!await file.exists()) {
    throw Exception('The CSV file $csvFile is not found.');
  }

  final contents = await file.readAsString();
  if (contents.trim().isEmpty) {
    throw Exception('Unable to read $csvFile.');
  }

  // Auto-detects EOL.
  final rows = const CsvToListConverter().convert(contents);

  if (rows.isEmpty) {
    throw Exception('Invalid region information CSV file.');
  }

  final headers = rows.first.map((h) => h.toString()).toList();
  final subdivisionNameIndex = headers.indexOf("subdivision_name");
  final countryCodeIndex = headers.indexOf("country_code");
  final codeIndex = headers.indexOf("code");

  if (subdivisionNameIndex == -1 ||
      countryCodeIndex == -1 ||
      codeIndex == -1) {
    throw Exception('Invalid region information CSV file.');
  }

  for (var i = 1; i < rows.length; i++) {
    final row = rows[i];

    final subdivisionName = row[subdivisionNameIndex]?.toString() ?? '';
    final countryCode = row[countryCodeIndex]?.toString() ?? '';
    final code = row[codeIndex]?.toString() ?? '';

    if (countryCode.isEmpty || subdivisionName.isEmpty) {
      continue; // skip bad rows
    }

    region._records.putIfAbsent(countryCode, () => []);

    region._records[countryCode]!.add({subdivisionName.toUpperCase(): code});
  }

  return region;
}