This method is safe to call from multiple threads. It performs a double-checked + * locking pattern using {@code loadLock} to initialize the data only once. */ - private void initCountries() { - Objects.requireNonNull(countriesFile); - countries = new HashMap<>(); - try (CSVParser parser = CSVFormat.DEFAULT.parse(new InputStreamReader(countriesFile, StandardCharsets.UTF_8))) { - for (CSVRecord line : parser) { - Country country = new Country(); - country.setName(line.get(0)); - countries.put(country.getName(), country); + private void ensureLoaded() { + if (airports != null && countries != null) { + return; + } + synchronized (loadLock) { + if (airports != null && countries != null) { + return; } - } catch (IOException exception) { - throw new IllegalStateException(exception.getMessage()); + loadResources(); } } /** - * Initiate airports map. + * Load countries and airports from the bundled CSV resources into memory. + * + *
The method reads two CSV resource files (COUNTRIES_RESOURCE and AIRPORTS_RESOURCE),
+ * creates Country and Airport instances and populates internal maps. If a resource is not
+ * found or an I/O error occurs, this method throws an IllegalStateException wrapping the
+ * original cause.
+ *
+ * @throws IllegalStateException if a resource file cannot be found or an I/O error occurs
+ * while reading the CSV files
*/
- private void initAirports() {
- Objects.requireNonNull(airportsFile);
- airports = new HashMap<>();
- try (CSVParser parser = CSVFormat.DEFAULT.parse(new InputStreamReader(airportsFile, StandardCharsets.UTF_8))) {
- for (CSVRecord line : parser) {
- Airport airport = new Airport();
- airport.setName(line.get(1));
- airport.setCity(line.get(2));
- airport.setCountry(countries.get(line.get(3)));
- airport.setIata(line.get(4));
- airport.setIcao(line.get(5));
- airport.setLatitude(Double.parseDouble(line.get(6)));
- airport.setLongitude(Double.parseDouble(line.get(7)));
- airport.setAltitude(Integer.parseInt(line.get(8)));
- airport.setTimezone(line.get(9));
- airport.setDst(line.get(10));
- airports.put(airport.getIcao(), airport);
+ private void loadResources() {
+ Map When this method is called the first time, it triggers loading of the underlying
+ * country and airport resources. Subsequent calls return the cached map. The returned
+ * map is the internal map instance (not a defensive copy).
+ *
+ * @return the map of ICAO -> Airport
+ */
@Override
public Map