org.meeuw.i18n:i18n-regions-open-location-code

Provides open location code areas as region objects

License

License

GroupId

GroupId

org.meeuw.i18n
ArtifactId

ArtifactId

i18n-regions-open-location-code
Last Version

Last Version

0.4
Release Date

Release Date

Type

Type

jar
Description

Description

Provides open location code areas as region objects

Download i18n-regions-open-location-code

How to add to project

<!-- https://jarcasting.com/artifacts/org.meeuw.i18n/i18n-regions-open-location-code/ -->
<dependency>
    <groupId>org.meeuw.i18n</groupId>
    <artifactId>i18n-regions-open-location-code</artifactId>
    <version>0.4</version>
</dependency>
// https://jarcasting.com/artifacts/org.meeuw.i18n/i18n-regions-open-location-code/
implementation 'org.meeuw.i18n:i18n-regions-open-location-code:0.4'
// https://jarcasting.com/artifacts/org.meeuw.i18n/i18n-regions-open-location-code/
implementation ("org.meeuw.i18n:i18n-regions-open-location-code:0.4")
'org.meeuw.i18n:i18n-regions-open-location-code:jar:0.4'
<dependency org="org.meeuw.i18n" name="i18n-regions-open-location-code" rev="0.4">
  <artifact name="i18n-regions-open-location-code" type="jar" />
</dependency>
@Grapes(
@Grab(group='org.meeuw.i18n', module='i18n-regions-open-location-code', version='0.4')
)
libraryDependencies += "org.meeuw.i18n" % "i18n-regions-open-location-code" % "0.4"
[org.meeuw.i18n/i18n-regions-open-location-code "0.4"]

Dependencies

compile (6)

Group / Artifact Type Version
org.meeuw.i18n : i18n-regions jar 0.4
javax.annotation : javax.annotation-api Optional jar 1.3.2
com.google.openlocationcode : openlocationcode jar 1.0.4
javax.validation : validation-api Optional jar 2.0.1.Final
org.checkerframework : checker-qual jar 2.9.0
javax.persistence : javax.persistence-api Optional jar 2.2

test (4)

Group / Artifact Type Version
org.hibernate.validator : hibernate-validator jar 6.0.2.Final
javax.el : javax.el-api jar 3.0.0
junit : junit jar 4.12
org.assertj : assertj-core jar 3.12.2

Project Modules

There are no modules declared in this project.

geographical regions

Build Status Maven Central snapshots javadoc codecov

Introduction

This project was started to be able to make better use of CountryCode's from nv-i18n

Using CountryCode as a value in your application has several drawbacks:

  1. It is not extensible. If you need a value not in that enum, you’re stuck.

  2. It for example does not contain 'former countries', so e.g. the birth country of a person, or the country of a movie cannot be stored as a 'CountryCode'.

  3. It’s only applicable to countries, no other regions.

I decided to wrap CountryCode in a class CurrentCountry, which implements a Region interface, which makes it possible to make other implementation of Region too, and to address all the above issues. You have to use Region instead of CountryCode as the type of your variable then.

Architecture

The central interface of this module is org.meeuw.i18n.regions.Region, which represents some geographical region.

Instances are created via java service providers implementing org.meeuw.i18n.regions.spi.RegionProvider (registered via META-INF/services), which are all managed by org.meeuw.i18n.regions.RegionService.

Providers are distributed via different artifacts, so you can in that way select what kind of regions the service should provide.

Providers

Countries

If you only need countries, you can take a dependency on org.meeuw.i18n:i18n-regions-countries

It provides:

all countires implement an interface org.meeuw.i18n.countries.Country

Subdivisions of countries

Continents

A list of codes for the continents is provided in org.meeuw.i18n:i18n-regions-continents

More

In the same fashion arbitrary region implementations can easily be plugged in. This project also provides a region implementation based on google’s 'open location code'.

Persistence

org.meeuw.i18n.regions.persistence.RegionToStringConverter is meant to arrange JPA persistence of Region objects to the database. We want the iso code to be used as simple strings in a database column or so.

This will also deal gracefully with codes which gets unassigned, because RegionService#getByCode will also fall back to formerly assigned codes.

e.g.

@ElementCollection
@Convert(converter = RegionToStringConverter.class)
protected List<org.meeuw.i18n.regions.Region> countries;

The converter is marked as autoApply, so in principle it is not needed to add this @Convert annotation explicitely, if this converter is available in your persistence.xml. Or e.g. its equivalent like this:

@EntityScan(basePackages = { ...}, basePackageClasses = {org.meeuw.i18n.regions.persistence.RegionToStringConverter.class})

XML Binding

The Region interface is JAXB-annotated to be marshallable to XML, which obviously should happen by the (ISO) code string. This can also be used for json.

Translations

The region interface also provides Region#getName(Locale) to retrieve the name of the region in the given locale. For many countries/locales this is supported by the JVM. Missing values can be provided via the Regions resource bundle.

Validation

Given a certain field with type Region (or one of its sub types) you may still find that makes too many values available. Therefore, we also provide some javax.validation.ConstraintValidator and associated annotations to limit possible values.

e.g.

protected List<
        // valid are countries (further validated by @ValidCountry), and a list of codes.
   org.meeuw.i18n.regions.
        @ValidRegion(classes = {Country.class}, includes = {"GB-ENG", "GB-NIR", "GB-SCT", "GB-WLS"})
        @ValidCountry(value = ValidCountry.OFFICIAL | ValidCountry.USER_ASSIGNED | ValidCountry.FORMER, excludes = {"XN"})
        @NotNull Region> countries;

or, if you prefer, on the collection itself:

    @ValidCountry(value = ValidCountry.OFFICIAL | ValidCountry.USER_ASSIGNED | ValidCountry.FORMER, includes = {"GB-ENG", "GB-NIR", "GB-SCT", "GB-WLS"})
    protected List<org.meeuw.i18n.regions.Region> countries;

This list will not validate if you add Regions which don’t follow the given rules.

It can also be used on java.util.Locale, which contains a country component too:

 protected List<
        @ValidRegion(classes = {Country.class})
        @ValidCountry(value = ValidCountry.OFFICIAL | ValidCountry.USER_ASSIGNED | ValidCountry.FORMER, excludes = {"XN"})
        @Language(mayContainCountry = true)
        @NotNull Locale> languages;

(For completeness also @Language is provided).

As a utility there is org.meeuw.i18n.regions.validation.RegionValidatorService which can be used to filter a stream of regions (e.g. RegionService#values()) based on the settings of these annotations.

 // A list of all valid regions for the property 'countries' of the 'MediaObject'
 return RegionService.getInstance().values()
            .filter(RegionValidatorService.getInstance().fromProperty(MediaObject.class, "countries"))
            .sorted(Regions.sortByName(LanguageCode.nl));

Optional dependencies

Several dependencies are marked optional in the pom.xml. E.g. the annotations used to arrange XML bindings and validation are not present (anymore) in java 11. If they are not present, this will not make it impossible to use the classes, you just cannot use JAXB, JPA, validation or whatever the missing dependency is related to. It’s only about annotations so that doesn’t cause (by the JSR-175 specification) problems.

Building and Jigsaw

This projects needs to build with java 11. It produces byte code compatible for java 8 though (besides module-info.class) The goal is to be compatible with jigsaw, which was introduced in java 9.

If you use java 11 then you can require org.meeuw.i18n.regions in module-info.java.

Testing

Besides the usual junit test in src/test, in the tests folder I collect some sample projects to test this stuff out by hand. Try e.g.

cd tests/springboot
mvn spring-boot:run

There are also tests in 'blackbox-testing'. Mainly testing validation code (because JPMS).

To achieve a proper report of test coverage the module 'report-aggregation' just depends on everything together witht some jacoco plugin configuration.

Logging

Some logging happens via the java.util.logging framework to avoid any extra dependencies.

When you use slf4j or logback or so you could take a dependency to catch such logging in your logging framework of choice.

<dependency>
  <!-- region service uses java.util.logging. This makes it log to logback as springboot does -->
  <groupId>org.slf4j</groupId>
  <artifactId>jul-to-slf4j</artifactId>
  <version>1.7.25</version>
</dependency>

There are very few log events, it is not important.

Release notes

Release notes can be found here.

Testing and JPMS

Find my findings here

Versions

Version
0.4