Skip to content

Commit

Permalink
Merge pull request #11 from tomaytotomato/3-native-localised-name-fix
Browse files Browse the repository at this point in the history
3 Fix localised names lookup (native name)
  • Loading branch information
tomaytotomato authored Aug 9, 2024
2 parents 51b3d14 + db2057e commit 76af5f5
Show file tree
Hide file tree
Showing 24 changed files with 361 additions and 52 deletions.
5 changes: 5 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,16 @@ name: Build

on:
push:
branches:
- master
paths:
- 'library/src/**'
- 'pom.xml'
- '.github/**'

pull_request:
branches:
- master
paths:
- 'library/src/**'
- 'pom.xml'
Expand Down
4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 16 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,25 +47,22 @@ public class Main {

```

## What can location4j do?

Here is an overview of the core functionality that location4j offers

| Feature | Supported | Object |
|------------------------------|-----------|----------|
| Search (free text) || Location |
| Find All Countries || Country |
| Find Country by Id || Country |
| Find Country by ISO2 code || Country |
| Find Country by ISO3 code || Country |
| Find Country by name || Country |
| Find Country by Native name || Country |
| Find Countries by State name || Country |
| Find States by State name || State |
| Find State by State Id || State |
| Find States by State code || State |
| Find City by City Id || City |
| Find Cities by City name || City |
| Feature | Supported | Object | Example |
|--------------------------------|-----------|----------|-------------------------------------------------------------------------|
| Search (free text) || Location | `search("Canada, Alberta")` -> `[Location("Alberta", "Canada")]` |
| Find All Countries || Country | `findAllCountries()` -> `[Country("Belgium"), Country("Canada"), ...]` |
| Find Country by Id || Country | `findCountryById(1)` -> `Optional[Country("Afghanistan")]` |
| Find Country by ISO2 code || Country | `findCountryByISO2Code("CA")` -> `Optional[Country("Canada")]` |
| Find Country by ISO3 code || Country | `findCountryByISO3Code("CAN")` -> `Optional[Country("Canada")]` |
| Find Country by Name || Country | `findCountryByName("Canada")` -> `Optional[Country("Canada")]` |
| Find Country by Localised name || Country | `findCountryByLocalisedName("Belgique")` -> `Optional[Country("Belgium")]` |
| Find Countries by State name || Country | `findAllCountriesByStateName("Texas")` -> `[Country("USA")]` |
| Find States by State name || State | `findAllStatesByStateName("Texas")` -> `[State("Texas", "USA")]` |
| Find State by State Id || State | `findStateById(5)` -> `Optional[State("California", "USA")]` |
| Find States by State code || State | `findAllStatesByStateCode("CA")` -> `[State("California", "USA")]` |
| Find City by City Id || City | `findCityById(10)` -> `Optional[City("Los Angeles", "California")]` |
| Find Cities by City name || City | `findAllCitiesByCityName("San Francisco")` -> `[City("San Francisco", "California")]` |


🟢 location4j can parse free text strings with or without punctuation or capitalisation e.g.
> San Francisco, CA, USA
Expand Down
24 changes: 10 additions & 14 deletions library/src/main/java/com/tomaytotomato/LocationService.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,19 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.logging.Logger;

/**
* This class provides simple lookups for Country, State and City information.
*/
public class LocationService implements FindCountry, FindState, FindCity {

private final Logger logger = Logger.getLogger(this.getClass().getPackage().getName() + this.getClass().getName());

private final List<Country> countries;
/**
* One-to-one mappings (1:1)
*/
private final Map<String, Country> countryNameToCountryMap = new HashMap<>();
private final Map<Integer, Country> countryIdToCountryMap = new HashMap<>();
private final Map<String, Country> countryNativeNameToCountry = new HashMap<>();
private final Map<String, Country> localisedNameToCountryMap = new HashMap<>();
private final Map<String, Country> iso2CodeToCountryMap = new HashMap<>();
private final Map<String, Country> iso3CodeToCountryMap = new HashMap<>();
private final Map<Integer, State> stateIdToStateMap = new HashMap<>();
Expand Down Expand Up @@ -73,11 +70,10 @@ private void buildDataStructures() {
countries.forEach(country -> {
countryIdToCountryMap.put(country.getId(), country);
countryNameToCountryMap.put(keyMaker(country.getName()), country);
if (Objects.isNull(country.getNativeName()) || country.getNativeName().isEmpty()) {
logger.warning("Country has null native name, skipping mapping: " + country.getName());
} else {
countryNativeNameToCountry.put(keyMaker(country.getNativeName()), country);
}

localisedNameToCountryMap.put(keyMaker(country.getNativeName()), country);
country.getTranslations().values().stream().map(this::keyMaker)
.forEach(translatedName -> localisedNameToCountryMap.put(translatedName, country));
iso2CodeToCountryMap.put(keyMaker(country.getIso2()), country);
iso3CodeToCountryMap.put(keyMaker(country.getIso3()), country);

Expand Down Expand Up @@ -121,12 +117,12 @@ public Optional<Country> findCountryByName(String countryName) {
}

@Override
public Optional<Country> findCountryByNativeName(String nativeName) {
if (Objects.isNull(nativeName) || nativeName.isEmpty()) {
throw new IllegalArgumentException("Country Native Name cannot be null or empty");
public Optional<Country> findCountryByLocalisedName(String localisedName) {
if (Objects.isNull(localisedName) || localisedName.isEmpty()) {
throw new IllegalArgumentException("Country Localised Name cannot be null or empty");
}
nativeName = textNormaliser.normalise(nativeName);
return Optional.ofNullable(countryNativeNameToCountry.get(nativeName));
localisedName = textNormaliser.normalise(localisedName);
return Optional.ofNullable(localisedNameToCountryMap.get(localisedName));
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import java.util.Map;

/**
* Allows adding custom aliases for Country, State and City
* Allows adding custom aliases for countries, states and cities
*/
public interface LocationAliases {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@
import com.tomaytotomato.model.Country;
import java.util.List;

/**
* Loads countries from the location4j.jar and provides it to any classes that need it.
*/
public interface CountriesDataLoader {

/**
* Returns a list of {@link Country} after loading them from disk
* @return list of countries
*/
List<Country> getCountries();

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@

/**
* The default loader for retrieving Countries from the DEFAULT_FILE located in the location4j.jar
*
*/
public class DefaultCountriesDataLoaderImpl implements CountriesDataLoader {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
import com.tomaytotomato.model.Location;
import com.tomaytotomato.model.State;

/**
* Converts {@link Country}, {@link State} and {@link City} objects into {@link Location} objects
*/
public interface LocationMapper {

Location toLocation(Country country);
Expand Down
11 changes: 10 additions & 1 deletion library/src/main/java/com/tomaytotomato/model/City.java
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package com.tomaytotomato.model;


import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Objects;

/**
* Represents a city with various attributes such as name, state, and country.
* <p>
* This class provides methods to access city details including geographic coordinates,
* country and state associations, and other identifiers.
* </p>
*/
public class City implements Serializable {

private static final long serialVersionUID = 1L;
Expand All @@ -21,6 +27,9 @@ public class City implements Serializable {
private BigDecimal latitude;
private BigDecimal longitude;

/**
* Default constructor for City.
*/
City() {}

public Integer getId() {
Expand Down
6 changes: 6 additions & 0 deletions library/src/main/java/com/tomaytotomato/model/Country.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
import java.util.Map;
import java.util.Objects;

/**
* Represents a country with various attributes such as name, codes, and geographic information.
* <p>
* This class provides methods to access country details, including currency, region, and states.
* </p>
*/
public class Country implements Serializable {

private static final long serialVersionUID = 1L;
Expand Down
27 changes: 26 additions & 1 deletion library/src/main/java/com/tomaytotomato/model/Location.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

import java.math.BigDecimal;

/**
* Represents a location result class, used for returning information on a location search.
* <p>
* This class provides methods to access details of a location, including its geographic
* coordinates, country, state, and city information.
* </p>
*/
public class Location {

private String countryName;
Expand All @@ -17,9 +24,28 @@ public class Location {
private BigDecimal latitude;
private BigDecimal longitude;

/**
* Default constructor for Location.
*/
public Location() {
}

/**
* Constructs a new Location with the specified attributes.
*
* @param countryName the name of the country
* @param countryId the unique identifier of the country
* @param countryIso2Code the ISO 3166-1 alpha-2 code of the country
* @param countryIso3Code the ISO 3166-1 alpha-3 code of the country
* @param state the name of the state
* @param stateId the unique identifier of the state
* @param stateCode the code of the state
* @param stateName the full name of the state
* @param city the name of the city
* @param cityId the unique identifier of the city
* @param latitude the latitude of the location
* @param longitude the longitude of the location
*/
public Location(String countryName, Integer countryId, String countryIso2Code,
String countryIso3Code, String state, Integer stateId, String stateCode, String stateName, String city,
Integer cityId, BigDecimal latitude, BigDecimal longitude) {
Expand Down Expand Up @@ -218,6 +244,5 @@ public Location build() {
return new Location(countryName, countryId, countryIso2Code, countryIso3Code, state, stateId,
stateCode, stateName, city, cityId, latitude, longitude);
}

}
}
25 changes: 25 additions & 0 deletions library/src/main/java/com/tomaytotomato/model/State.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@
import java.util.List;
import java.util.Objects;

/**
* Represents a state data class.
* <p>
* This class provides methods to access state details, including its geographic coordinates,
* country association, and the list of cities within the state.
* </p>
*/
public class State implements Serializable {

private static final long serialVersionUID = 1L;
Expand All @@ -21,8 +28,26 @@ public class State implements Serializable {
private BigDecimal latitude;
private BigDecimal longitude;

/**
* Default constructor for State.
*/
State() {}

/**
* Constructs a new State with the specified attributes.
*
* @param id the unique identifier of the state
* @param countryId the unique identifier of the country associated with the state
* @param countryName the name of the country associated with the state
* @param countryIso2Code the ISO 3166-1 alpha-2 code of the country
* @param countryIso3Code the ISO 3166-1 alpha-3 code of the country
* @param name the name of the state
* @param type the type or classification of the state (e.g., province, region)
* @param stateCode the code of the state
* @param cities the list of cities within the state
* @param latitude the latitude of the state's geographic center
* @param longitude the longitude of the state's geographic center
*/
public State(Integer id, Integer countryId, String countryName, String countryIso2Code,
String countryIso3Code, String name, String type, String stateCode, List<City> cities,
BigDecimal latitude, BigDecimal longitude) {
Expand Down
19 changes: 19 additions & 0 deletions library/src/main/java/com/tomaytotomato/model/TimeZone.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@
import java.io.Serializable;
import java.util.Objects;

/**
* Represents a timezone data class.
* <p>
* This class provides methods to access timezone details, including the zone name,
* abbreviation, and GMT offset information.
* </p>
*/
public class TimeZone implements Serializable {

private static final long serialVersionUID = 1L;
Expand All @@ -13,9 +20,21 @@ public class TimeZone implements Serializable {
private Integer gmtOffset;
private String gmtOffsetName;

/**
* Default constructor for TimeZone.
*/
TimeZone() {
}

/**
* Constructs a new TimeZone with the specified attributes.
*
* @param zoneName the name of the timezone
* @param abbreviation the abbreviation of the timezone
* @param tzName the full name of the timezone
* @param gmtOffset the GMT offset in seconds
* @param gmtOffsetName the human-readable name for the GMT offset
*/
public TimeZone(String zoneName, String abbreviation, String tzName, Integer gmtOffset,
String gmtOffsetName) {
this.zoneName = zoneName;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import java.util.Objects;

/**
* Default text normaliser, lowercases text, removes unnecessary punctuation characters and spaces
*/
public class DefaultTextNormaliser implements TextNormaliser {

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.tomaytotomato.text.normaliser;

/**
* Normalises text input before being used in lookups or searches
*/
public interface TextNormaliser {

String normalise(String text);
Expand Down
Loading

0 comments on commit 76af5f5

Please sign in to comment.