diff --git a/buildtools/src/main/java/com/tomaytotomato/JsonToBinaryConverter.java b/buildtools/src/main/java/com/tomaytotomato/JsonToBinaryConverter.java index 414b8b4..b118ceb 100644 --- a/buildtools/src/main/java/com/tomaytotomato/JsonToBinaryConverter.java +++ b/buildtools/src/main/java/com/tomaytotomato/JsonToBinaryConverter.java @@ -3,7 +3,9 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; +import com.tomaytotomato.model.City; import com.tomaytotomato.model.Country; +import com.tomaytotomato.model.State; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -16,7 +18,7 @@ /** * This tool is used to transform the opensource JSON data into a binary format for use by - * location4j + * location4j. */ public class JsonToBinaryConverter { @@ -38,21 +40,33 @@ public static void main(String[] args) { var jsonString = new String(inputStream.readAllBytes()); - // fix data, for inconsistent namings of JSON properties + // Fix data for inconsistent namings of JSON properties var modifiedJson = fixJSONPropertyNames(jsonString); ObjectMapper mapper = new ObjectMapper(); mapper.setPropertyNamingStrategy(new SnakeCaseStrategy()); - var countries = mapper.readValue(modifiedJson, new TypeReference>() { + List countries = mapper.readValue(modifiedJson, new TypeReference>() { }); + // Build links between each object + List updatedCountries = countries.stream().map(country -> { + List updatedStates = country.getStates().stream().map(state -> { + + List cities = state.getCities().stream() + .map(city -> buildCityLinksToStateAndCountry(city, state, country)).toList(); + + return buildStateLinksToCountry(country, state, cities); + }).toList(); + return buildCountry(country, updatedStates); + }).toList(); + Path outputFile = Paths.get(OUTPUT_FILE).toAbsolutePath(); logger.log(Level.INFO, () -> String.format("Serializing data to binary file at: %s", outputFile)); try (var fileOutputStream = new FileOutputStream(outputFile.toFile()); var objectOutputStream = new ObjectOutputStream(fileOutputStream)) { - objectOutputStream.writeObject(countries); + objectOutputStream.writeObject(updatedCountries); logger.info("Data successfully serialized to binary format."); } } catch (IOException e) { @@ -71,7 +85,70 @@ private static String fixJSONPropertyNames(String jsonString) { modifiedJson = modifiedJson.replace("\"gmtOffsetName\"", "\"gmt_offset_name\""); modifiedJson = modifiedJson.replace("\"tzName\"", "\"tz_name\""); modifiedJson = modifiedJson.replace("\"emojiU\"", "\"emoji_u\""); + modifiedJson = modifiedJson.replace("\"iso2\"", "\"iso2_code\""); + modifiedJson = modifiedJson.replace("\"iso3\"", "\"iso3_code\""); + return modifiedJson; } + private static Country buildCountry(Country country, List states) { + return Country.builder() + .id(country.getId()) + .name(country.getName()) + .iso2Code(country.getIso2Code()) + .iso3Code(country.getIso3Code()) + .phoneCode(country.getPhoneCode()) + .numericCode(country.getNumericCode()) + .capital(country.getCapital()) + .currency(country.getCurrency()) + .currencyName(country.getCurrencyName()) + .currencySymbol(country.getCurrencySymbol()) + .tld(country.getTld()) + .nativeName(country.getNativeName()) + .region(country.getRegion()) + .regionId(country.getRegionId()) + .subregion(country.getSubregion()) + .subregionId(country.getSubregionId()) + .states(states) + .nationality(country.getNationality()) + .timezones(country.getTimezones()) + .translations(country.getTranslations()) + .latitude(country.getLatitude()) + .longitude(country.getLongitude()) + .emoji(country.getEmoji()) + .emojiU(country.getEmojiU()) + .build(); + } + + private static State buildStateLinksToCountry(Country country, State state, List cities) { + return State.builder() + .id(state.getId()) + .name(state.getName()) + .type(state.getType()) + .countryId(country.getId()) + .countryName(country.getName()) + .countryIso2Code(country.getIso2Code()) + .countryIso3Code(country.getIso3Code()) + .stateCode(state.getStateCode()) + .latitude(state.getLatitude()) + .longitude(state.getLongitude()) + .cities(cities) + .build(); + } + + private static City buildCityLinksToStateAndCountry(City city, State state, Country country) { + return City.builder() + .id(city.getId()) + .countryId(country.getId()) + .countryName(country.getName()) + .countryIso2Code(country.getIso2Code()) + .countryIso3Code(country.getIso3Code()) + .stateCode(state.getStateCode()) + .stateId(state.getId()) + .stateName(state.getName()) + .name(city.getName()) + .longitude(city.getLongitude()) + .latitude(city.getLatitude()) + .build(); + } } diff --git a/location4j/src/main/java/com/tomaytotomato/LocationService.java b/location4j/src/main/java/com/tomaytotomato/LocationService.java index 49e26cd..5d31dea 100644 --- a/location4j/src/main/java/com/tomaytotomato/LocationService.java +++ b/location4j/src/main/java/com/tomaytotomato/LocationService.java @@ -87,8 +87,8 @@ private void buildDataStructures() { .forEach( translatedName -> localisedNameToCountryMap.put(translatedName, country)); - iso2CodeToCountryMap.put(keyMaker(country.getIso2()), country); - iso3CodeToCountryMap.put(keyMaker(country.getIso3()), country); + iso2CodeToCountryMap.put(keyMaker(country.getIso2Code()), country); + iso3CodeToCountryMap.put(keyMaker(country.getIso3Code()), country); country.getStates() .forEach( diff --git a/location4j/src/main/java/com/tomaytotomato/SearchLocationService.java b/location4j/src/main/java/com/tomaytotomato/SearchLocationService.java index 9c80f8b..b0ede83 100644 --- a/location4j/src/main/java/com/tomaytotomato/SearchLocationService.java +++ b/location4j/src/main/java/com/tomaytotomato/SearchLocationService.java @@ -77,8 +77,8 @@ private static Location buildLocationResult(Country topCountry, State topState, .countryName(topCountry.getName()) .countryId(topCountry.getId()) - .countryIso2Code(topCountry.getIso2()) - .countryIso3Code(topCountry.getIso3()) + .countryIso2Code(topCountry.getIso2Code()) + .countryIso3Code(topCountry.getIso3Code()) .latitude(topCountry.getLatitude()) .longitude(topCountry.getLongitude()); @@ -148,8 +148,8 @@ private void addAliases() { private void buildCountryLookups(Country country) { countryNameToCountryMap.put(keyMaker(country.getName()), country); countryIdToCountryMap.put(country.getId(), country); - iso2CodeToCountryMap.put(keyMaker(country.getIso2()), country); - iso3CodeToCountryMap.put(keyMaker(country.getIso3()), country); + iso2CodeToCountryMap.put(keyMaker(country.getIso2Code()), country); + iso3CodeToCountryMap.put(keyMaker(country.getIso3Code()), country); } /** @@ -159,37 +159,16 @@ private void buildCountryLookups(Country country) { * @param country The country the state belongs to. */ private void buildStateLookups(State state, Country country) { - state.setCountryId(country.getId()); - state.setCountryName(country.getName()); - state.setCountryIso2Code(country.getIso2()); - state.setCountryIso3Code(country.getIso3()); - stateIdToStateMap.put(state.getId(), state); stateNameToStatesMap.computeIfAbsent(keyMaker(state.getName()), k -> new ArrayList<>()) .add(state); stateCodeToStatesMap.computeIfAbsent(keyMaker(state.getStateCode()), k -> new ArrayList<>()) .add(state); - state.getCities().forEach(city -> buildCityLookups(city, state, country)); + state.getCities().forEach(city -> cityNameToCitiesMap.computeIfAbsent(keyMaker(city.getName()), + k -> new ArrayList<>()).add(city)); } - /** - * Maps a city to various lookup maps. - * - * @param city The city to be mapped. - * @param state The state the city belongs to. - * @param country The country the city belongs to. - */ - private void buildCityLookups(City city, State state, Country country) { - city.setCountryId(country.getId()); - city.setCountryName(country.getName()); - city.setCountryIso2Code(country.getIso2()); - city.setCountryIso3Code(country.getIso3()); - city.setStateId(state.getId()); - city.setStateName(state.getName()); - city.setStateCode(state.getStateCode()); - cityNameToCitiesMap.computeIfAbsent(keyMaker(city.getName()), k -> new ArrayList<>()).add(city); - } /** * Normalizes a key for consistent lookup. diff --git a/location4j/src/main/java/com/tomaytotomato/mapper/DefaultLocationMapper.java b/location4j/src/main/java/com/tomaytotomato/mapper/DefaultLocationMapper.java index e155747..99aabbe 100644 --- a/location4j/src/main/java/com/tomaytotomato/mapper/DefaultLocationMapper.java +++ b/location4j/src/main/java/com/tomaytotomato/mapper/DefaultLocationMapper.java @@ -12,8 +12,8 @@ public Location toLocation(Country country) { return Location.builder() .countryName(country.getName()) .countryId(country.getId()) - .countryIso2Code(country.getIso2()) - .countryIso3Code(country.getIso3()) + .countryIso2Code(country.getIso2Code()) + .countryIso3Code(country.getIso3Code()) .latitude(country.getLatitude()) .longitude(country.getLongitude()) .build(); diff --git a/location4j/src/main/java/com/tomaytotomato/model/City.java b/location4j/src/main/java/com/tomaytotomato/model/City.java index c2404e0..baa48f2 100644 --- a/location4j/src/main/java/com/tomaytotomato/model/City.java +++ b/location4j/src/main/java/com/tomaytotomato/model/City.java @@ -144,6 +144,11 @@ public void setStateCode(String stateCode) { this.stateCode = stateCode; } + public static Builder builder() { + return new Builder(); + } + + @Generated("IntelliJ") public static final class Builder { private Integer id; @@ -161,10 +166,6 @@ public static final class Builder { private Builder() { } - public static Builder aCity() { - return new Builder(); - } - public Builder id(Integer id) { this.id = id; return this; diff --git a/location4j/src/main/java/com/tomaytotomato/model/Country.java b/location4j/src/main/java/com/tomaytotomato/model/Country.java index fc05f82..7e9bbf6 100644 --- a/location4j/src/main/java/com/tomaytotomato/model/Country.java +++ b/location4j/src/main/java/com/tomaytotomato/model/Country.java @@ -21,9 +21,8 @@ public class Country implements Serializable { private Integer id; private String name; - private String iso3; - private String iso2; - private String zoneName; + private String iso3Code; + private String iso2Code; private String phoneCode; private String numericCode; private String capital; @@ -56,16 +55,12 @@ public String getName() { return name; } - public String getIso3() { - return iso3; + public String getIso3Code() { + return iso3Code; } - public String getIso2() { - return iso2; - } - - public String getZoneName() { - return zoneName; + public String getIso2Code() { + return iso2Code; } public String getPhoneCode() { @@ -148,14 +143,17 @@ public String getEmojiU() { return emojiU; } + public static Builder builder() { + return new Builder(); + } + @Generated("IntelliJ") public static final class Builder { private Integer id; private String name; - private String iso3; - private String iso2; - private String zoneName; + private String iso3Code; + private String iso2Code; private String phoneCode; private String numericCode; private String capital; @@ -180,10 +178,6 @@ public static final class Builder { private Builder() { } - public static Builder aCountry() { - return new Builder(); - } - public Builder id(Integer id) { this.id = id; return this; @@ -194,18 +188,13 @@ public Builder name(String name) { return this; } - public Builder iso3(String iso3) { - this.iso3 = iso3; - return this; - } - - public Builder iso2(String iso2) { - this.iso2 = iso2; + public Builder iso3Code(String iso3Code) { + this.iso3Code = iso3Code; return this; } - public Builder zoneName(String zoneName) { - this.zoneName = zoneName; + public Builder iso2Code(String iso2Code) { + this.iso2Code = iso2Code; return this; } @@ -313,7 +302,7 @@ public Country build() { Country country = new Country(); country.name = this.name; country.phoneCode = this.phoneCode; - country.iso3 = this.iso3; + country.iso3Code = this.iso3Code; country.longitude = this.longitude; country.currencyName = this.currencyName; country.numericCode = this.numericCode; @@ -321,7 +310,7 @@ public Country build() { country.capital = this.capital; country.region = this.region; country.translations = this.translations; - country.iso2 = this.iso2; + country.iso2Code = this.iso2Code; country.currencySymbol = this.currencySymbol; country.timezones = this.timezones; country.tld = this.tld; @@ -329,7 +318,6 @@ public Country build() { country.nativeName = this.nativeName; country.emoji = this.emoji; country.subregion = this.subregion; - country.zoneName = this.zoneName; country.regionId = this.regionId; country.latitude = this.latitude; country.id = this.id; @@ -351,9 +339,8 @@ public boolean equals(Object o) { } Country country = (Country) o; return Objects.equals(getId(), country.getId()) && Objects.equals(getName(), - country.getName()) && Objects.equals(getIso3(), country.getIso3()) - && Objects.equals(getIso2(), country.getIso2()) && Objects.equals( - getZoneName(), country.getZoneName()) && Objects.equals(getPhoneCode(), + country.getName()) && Objects.equals(getIso3Code(), country.getIso3Code()) + && Objects.equals(getIso2Code(), country.getIso2Code()) && Objects.equals(getPhoneCode(), country.getPhoneCode()) && Objects.equals(getNumericCode(), country.getNumericCode()) && Objects.equals(getCapital(), country.getCapital()) && Objects.equals(getCurrency(), country.getCurrency()) && Objects.equals( @@ -375,7 +362,7 @@ public boolean equals(Object o) { @Generated("IntelliJ") @Override public int hashCode() { - return Objects.hash(getId(), getName(), getIso3(), getIso2(), getZoneName(), getPhoneCode(), + return Objects.hash(getId(), getName(), getIso3Code(), getIso2Code(), getPhoneCode(), getNumericCode(), getCapital(), getCurrency(), getCurrencyName(), getCurrencySymbol(), getTld(), getNativeName(), getRegion(), getRegionId(), getSubregion(), getSubregionId(), getStates(), getNationality(), getTimezones(), getTranslations(), getLatitude(), diff --git a/location4j/src/main/java/com/tomaytotomato/model/State.java b/location4j/src/main/java/com/tomaytotomato/model/State.java index c3c2983..928c6ef 100644 --- a/location4j/src/main/java/com/tomaytotomato/model/State.java +++ b/location4j/src/main/java/com/tomaytotomato/model/State.java @@ -128,6 +128,11 @@ public void setCountryIso3Code(String countryIso3Code) { this.countryIso3Code = countryIso3Code; } + public static Builder builder() { + return new Builder(); + } + + @Generated("IntelliJ") public static final class Builder { private Integer id; @@ -145,10 +150,6 @@ public static final class Builder { private Builder() { } - public static Builder aState() { - return new Builder(); - } - public Builder id(Integer id) { this.id = id; return this; diff --git a/location4j/src/main/java/com/tomaytotomato/model/TimeZone.java b/location4j/src/main/java/com/tomaytotomato/model/TimeZone.java index 09f27e1..d615469 100644 --- a/location4j/src/main/java/com/tomaytotomato/model/TimeZone.java +++ b/location4j/src/main/java/com/tomaytotomato/model/TimeZone.java @@ -67,6 +67,7 @@ public String getGmtOffsetName() { return gmtOffsetName; } + @Generated("IntelliJ") public static final class Builder { private String zoneName; diff --git a/location4j/src/main/resources/location4j.bin b/location4j/src/main/resources/location4j.bin index c2291e8..17134a5 100644 Binary files a/location4j/src/main/resources/location4j.bin and b/location4j/src/main/resources/location4j.bin differ