Git Product home page Git Product logo

libaddressinput's Introduction

libaddressinput

Build Status

The libaddressinput project consists of two different libraries (one implemented in C++, one implemented in Java for Android) that use address metadata from Google's Address Data Service to assist application developers in collecting and handling postal addresses from all over the world.

These libraries can provide information about what input fields are required for a correct address input form for any country in the world and can validate an address to highlight input errors like missing required fields or invalid values.

C++

The C++ library (in very portable C++11) of libaddressinput is used in address-related projects in Chromium.

https://chromium.googlesource.com/chromium/src/+/master/third_party/libaddressinput/

Java

The Java library of libaddressinput is written for use in Android and includes an Android UI address input widget ready for use, but only the UI parts are tied to Android.

Non-UI code and tests can be run in Java SE, and the rest of the library could easily be adapted to run in any Java environment.

Mailing List

Using and developing libaddressinput is discussed on this mailing list:

https://groups.google.com/forum/#!forum/libaddressinput-discuss

License

Source code licensed under the Apache 2.0. Data licensed under the CC-BY 4.0

libaddressinput's People

Contributors

alanzhao1 avatar andyst avatar battre avatar dlyongemallo avatar evanstade avatar hagbard avatar jias0001 avatar jsankey avatar keghani avatar lararennie avatar mihnita avatar mohamedamir avatar parastoog avatar pcc avatar pkasting avatar pschanely avatar roes avatar roubert avatar rsolomakhin avatar sebsg avatar sockix avatar ssundarraj avatar tanderson-google avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

libaddressinput's Issues

Subdivisions need unique ids

When a subdivision (administrative area / locality / dependent locality) has no ISO id, the library uses the name as the key. This is especially visible for the Brazil localities and China localities / dependent localities. Now, the names of these subdivisions are known to change, causing the "id" to change, and leaving no connection between the old entry and the new entry.
This creates a problem for people wanting to normalize the data by having a "subdivision" table and an "address" table that references subdivisions by id, since subdivision changes leave no way to update the ids in the address table.

In commerceguys/addressing I resorted to generating an id from the sha1 hash of the key (to get a safe value), but that of course doesn't solve the main problem. Recent diff

-     "CN-33-6b5326-b2f6e2": {
+    "CN-33-6b5326-a139f5": {
         "locale": "zh-Latn",
         "country_code": "CN",
         "parent_id": "CN-33-6b5326",
-        "id": "CN-33-6b5326-b2f6e2",
-        "code": "绍兴县",
-        "name": "Shaoxing Xian",
+        "id": "CN-33-6b5326-a139f5",
+        "code": "上虞市",
+        "name": "Shangyu Shi",

(I am assuming this refers to the same subdivision. I've also seen Brazilian examples where that was more clear).

So, it would be great if the dataset could construct and provide some kind of a unique id, to make it easier for implementations to have the desired datamodel.

HK address data returned from the i18n address data service is different from what's in countryinfo.txt

http://i18napis.appspot.com/address/data/HK

{"lang": "zh-hant", "upper": "S", "sub_lnames": "KowloonHong Kong IslandNew Territories", "name": "HONG KONG", "sub_mores": "truetruetrue", "require": "AS", "state_name_type": "area", "id": "data/HK", "languages": "zh-hanten", "lfmt": "%N%n%O%n%A%n%C%n%S", "sub_keys": "九龍香港島~新界", "key": "HK", "locality_name_type": "district", "fmt": "%S%n%C%n%A%n%O%n%N"}

countryinfo.txt

data/HK={"id":"data/HK","key":"HK","name":"HONG KONG","lang":"zh-hant","languages":"zh-hanten","fmt":"%S%n%A%n%O%n%N","lfmt":"%N%n%O%n%A%n%S","require":"AS","upper":"S","state_name_type":"area","sub_keys":"九龍香港島新界","sub_lnames":"KowloonHong Kong IslandNew Territories","sub_mores":"falsefalse~true"}

Differences:
fmt/lfmt values are missing %C
sub_mores values are different
locality_name_type key is missing

AE address data returned from the i18n address data service is different from what's in countryinfo.txt

http://i18napis.appspot.com/address/data/AE
returns

{"lang": "ar", "sub_lnames": "Abu DhabiFujairahUmm Al QuwainSharjahDubaiRas al KhaimahAjmān", "name": "UNITED ARAB EMIRATES", "require": "AS", "state_name_type": "emirate", "id": "data/AE", "languages": "ar", "lfmt": "%N%n%O%n%A%n%S", "sub_keys": "أبو ظبيالفجيرةام القيوينإمارة الشارقةّإمارة دبيّإمارة رأس الخيمةعجمان", "key": "AE", "sub_isoids": "AZFUUQSHDURKAJ", "fmt": "%N%n%O%n%A%n%S"}

countryinfo.txt:
data/AE={"id":"data/AE","key":"AE","name":"UNITED ARAB EMIRATES","fmt":"%N%n%O%n%A%n%C","require":"AC"}

Countries that need postal codes

build doesn't work

Could be related to http://stackoverflow.com/questions/18153739/android-studio-plugin-with-id-android-library-not-found

PH7785-2:java paul$ gradle
Download https://repo1.maven.org/maven2/com/android/tools/build/gradle/0.8.3/gradle-0.8.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/lint/lint/22.5.3/lint-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/build/builder/0.8.3/builder-0.8.3.pom
Download https://repo1.maven.org/maven2/net/sf/proguard/proguard-gradle/4.10/proguard-gradle-4.10.pom
Download https://repo1.maven.org/maven2/net/sf/proguard/proguard-parent/4.10/proguard-parent-4.10.pom
Download https://repo1.maven.org/maven2/com/android/tools/lint/lint-checks/22.5.3/lint-checks-22.5.3.pom
Download https://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.2.2/ecj-4.2.2.pom
Download https://repo1.maven.org/maven2/com/android/tools/sdklib/22.5.3/sdklib-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/ddms/ddmlib/22.5.3/ddmlib-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/build/builder-model/0.8.3/builder-model-0.8.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/build/manifest-merger/22.5.3/manifest-merger-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/sdk-common/22.5.3/sdk-common-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/build/builder-test-api/0.8.3/builder-test-api-0.8.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/common/22.5.3/common-22.5.3.pom
Download https://repo1.maven.org/maven2/net/sf/proguard/proguard-base/4.10/proguard-base-4.10.pom
Download https://repo1.maven.org/maven2/com/android/tools/lint/lint-api/22.5.3/lint-api-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/dvlib/22.5.3/dvlib-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/layoutlib/layoutlib-api/22.5.3/layoutlib-api-22.5.3.pom
Download https://repo1.maven.org/maven2/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2.pom
Download https://repo1.maven.org/maven2/com/android/tools/build/gradle/0.8.3/gradle-0.8.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/lint/lint/22.5.3/lint-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/build/builder/0.8.3/builder-0.8.3.jar
Download https://repo1.maven.org/maven2/net/sf/proguard/proguard-gradle/4.10/proguard-gradle-4.10.jar
Download https://repo1.maven.org/maven2/com/android/tools/lint/lint-checks/22.5.3/lint-checks-22.5.3.jar
Download https://repo1.maven.org/maven2/org/eclipse/jdt/core/compiler/ecj/4.2.2/ecj-4.2.2.jar
Download https://repo1.maven.org/maven2/com/android/tools/sdklib/22.5.3/sdklib-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/ddms/ddmlib/22.5.3/ddmlib-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/build/builder-model/0.8.3/builder-model-0.8.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/build/manifest-merger/22.5.3/manifest-merger-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/sdk-common/22.5.3/sdk-common-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/build/builder-test-api/0.8.3/builder-test-api-0.8.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/common/22.5.3/common-22.5.3.jar
Download https://repo1.maven.org/maven2/net/sf/proguard/proguard-base/4.10/proguard-base-4.10.jar
Download https://repo1.maven.org/maven2/com/android/tools/lint/lint-api/22.5.3/lint-api-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/dvlib/22.5.3/dvlib-22.5.3.jar
Download https://repo1.maven.org/maven2/com/android/tools/layoutlib/layoutlib-api/22.5.3/layoutlib-api-22.5.3.jar
Download https://repo1.maven.org/maven2/org/ow2/asm/asm/4.0/asm-4.0.jar
Download https://repo1.maven.org/maven2/com/android/tools/external/lombok/lombok-ast/0.2.2/lombok-ast-0.2.2.jar

FAILURE: Build failed with an exception.

  • Where:
    Build file '/scm/oss/libaddressinput/java/build.gradle' line: 12

  • What went wrong:
    A problem occurred evaluating root project 'java'.

    Failed to apply plugin [id 'android-library']
    Gradle version 1.10 is required. Current version is 2.1. If using the gradle wrapper, try editing the distributionUrl in /scm/oss/libaddressinput/java/gradle/wrapper/gradle-wrapper.properties to gradle-1.10-all.zip

  • Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Total time: 51.931 secs

Ordering of Mexican provinces, name of the "Mexico" province

  1. The wikipedia page on MX ISO codes says:
    "Subdivision names are sorted in traditional Spanish alphabetical order: a-c, ch, d-l, ll, m-n, ñ, o-z."
    This traditional ordering is also used by UPU, but not by the dataset.

Expected sorting:
Campeche - Coahuila - Colima - Chiapas - Chihuahua
Dataset sorting:
Campeche - Chiapas - Chihuahua - Coahuila - Colima

  1. "Estado de México" should be just "México" (and ordered appropriately), as demonstrated by both ISO and UPU.

https://en.wikipedia.org/wiki/ISO_3166-2:MX
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/mexEn.pdf

Correct China Administrative Area data

China has 11 Cities/Areas, which don't belong to a Province or State.

Therefore, when we are querying the data, the District data is populated into City Field. For example, in the screenshot below,

image

"Changning Qu" is populated into the dropdown of the City Field. However, "Changning Qu" should be in the District Field.

One way to fix this, as also suggested by @bojanz is to duplicate the "administrative area" data, for example, from

data/CN/Shanghai Shi/Changning Qu

to

data/CN/Shanghai Shi/Shanghai Shi/Changning Qu

Sorting Code not included in the output of getEnvelopeAddress method

Using the android java library, the FormatInterpreter class contains a method getEnvelopeAddress(AddressData address) used to get the formatted address. This method does not include the sorting code that may have been set in the AddressData object.

For example French addresses may include a CEDEX. The widget successfully stores the CEDEX value in the sorting code field within AddressData, but the field is not included when using getEnvelopeAddress() producing an incorrect output.

Naming of three italian provinces

"Valle d'Aosta" should be "Aosta"
"Reggio nell'Emilia" should be "Reggio Emilia"
"Monza e della Brianza" should be "Monza e Brianza"

Sources:
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/itaEn.pdf
https://en.wikipedia.org/wiki/ISO_3166-2:IT

Reasoning:
"Valle d'Aosta" is the name of the region, but the name of the province is just "Aosta".
"Regio Emilia" is consistently used by UPU, ISO, and the italian site used as a source for Wikipedia: http://www.comuni-italiani.it/035/index.html
The official site of Monza e Brianza seems to use that form, just like ISO does.

These 3 are also the forms reported to us by our Italian users.

Mozambique

The dataset has an entry for Mozambique:
https://i18napis.appspot.com/address/data/MZ
This entry contains the postal code validation pattern, and example postal codes, but declares no fields, so the fallback ZZ format fields are used instead, but they don't include a postal code field at all.

So, the entry at least needs to have a list of fields that includes the postal code and administrative area.
Next, it should include the Mozambique provinces, as listed on:
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/mozEn.pdf

Estonia, Latvia, Lithuania

According to UPU for Estonia:

For large towns, the district is defined by the town and the post office. In other cases,
the district is defined by the region and the rural municipality.

This means that people in small towns write the region instead of the locality. Because of this, I've been getting bug reports and requests from Estonian users about adding the administrative_area (region) field for Estonia.

Based on that, it makes sense to me to add a non-required administrative_area field for Estonia, and define the 15 Estonian regions.

Incorrect forms for United Arab Emirates

We are running a large bookstore in UAE and tried to use requestAutocomplete however we have quickly discovered that the addresses it provides for UAE are useless.

A valid shipping address within Emirates has to contain at the very least:

  • First name and last name
  • PO BOX number (postcode equivalent)
  • Emirate name (state equivalent)

Address lines and city are useful but usually not required. The addressing system in Emirates is virtually nonexistent. Most places don't have a formal street address and most deliveries are made to PO boxes.

Missing address format, subdivisions for Peru

The subdivisions are listed on the UPU document:
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/perEn.pdf
#46 already confirmed that Peru needs postal codes.

The UPU document also mentions a sublocality field, but no locality field.
I geocoded the sample address and it placed Miraflores into "locality".
A quick wikipedia / google search also tells me that the correct label for this field is "District":
https://en.wikipedia.org/wiki/Miraflores_District,_Lima

Inconsistencies in dealing with overseas territories

The US has a number of overseas territories:

  • American Samoa (AS)
  • Federated States of Micronesia (FM)
  • Guam (GU)
  • Marshall Islands (MH)
  • Northern Mariana Islands (MP)
  • Palau (PW)
  • Puerto Rico (PR)
  • Virgin Islands (VI)

These territories are available as both US states, and as individual countries with their own country codes. UPU has no address format definitions for them, each one is a pointer to the US format, like this http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/mhlEn.pdf

However, their address formats in the dataset are inconsistent. The format for Puerto Rico specifies no administrative area field, but the formats for others specify an administrative area field.
For me it makes sense that no format has an administrative area field.

The same example can be seen for these Australian territories:

  • Cocos (Keeling) Islands (CC)
  • Christmas Islands (CXR)
  • Norfolk Island (NF)

All of them have an administrative area field, but it makes no sense since the islands themselves are the administrative areas.

Add the Town/City locality type

According to my previous addressing dataset (gathered with the help of our clients), United Kingdom and New Zealand (GB, NZ) use the "Town/City" label for the locality.

Google's dataset currently specifies "post town" for GB, which matches what UPU is saying.
However, Royal mail itself uses "City or town" on their own site:
https://dl.dropboxusercontent.com/u/10724055/royalmail.png

For New Zealand the situation is more clear, UPU uses "Town/City":
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/nzlEn.pdf
And so does the site of the New Zealand post:
https://dl.dropboxusercontent.com/u/10724055/nzpost.png

Dealing with countries that use only one address line

I've received reports from users in several countries* that the second address line is not used in their countries. And indeed, going to the sites of the AU & NZ post offices, only one line is rendered.

Was there ever a plan to split the %A token in the dataset into multiple tokens (one per address line)? I'm not sure how feasible such a thing would be (from a data gathering perspective, especially), but it's worth a discussion.

  • Australia, Estonia, Latvia, Lithuania, New Zealand, Russia, Finland

Indonesian labels

The state_name_type and locality_name_type for Indonesia need to change.
The state_name_type should be removed, so that it defaults to "province".
The locality_name_type should be set to a newly added "city_regency".

The dataset currently lists the state_name_type as "district":
https://i18napis.appspot.com/address/data/ID

According to Wikipedia and UPU, the state is "Province", the locality is "City/Regency", and the dependent locality is "District".

An odd detail is that UPU says that the provinces aren't used for mailing, but both your dataset and my previous one contain Indonesian provinces. That requires additional research.
UPU also mentions dependent localities, but the dataset currently doesn't specify that field being used (looks like it's rare?)

http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/idnEn.pdf
https://en.wikipedia.org/wiki/List_of_regencies_and_cities_of_Indonesia

In Germany the organization comes before the recipient

As reported in the PHP reimplementation of libaddressinput: commerceguys/addressing#34

Germany puts the organization before the recipient, just like 28 other countries (including Austria, France, Belgium, Switzerland).

UPU is a bit unclear about this:
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/deuEn.pdf
But the Deutsche post link is authoritative:
http://www.postadressglobal.com/de-de/country/deutschland/formatierung-und-strukturierung-deutscher-adressen/

Required postal codes in CZ, SK

A customer reported that CZ and SK have required postal codes, even though the dataset doesn't specify that.

UPU clearly confirms that for SK, but not for CZ, though all examples do have postal codes.
Furthermore, these used to be the same country, so it feels logical that they'd have the same rule.
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/czeEn.pdf
http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/svkEn.pdf

The czech post office seems to indicate all addresses have postal codes:
https://www.ceskaposta.cz/en/rady-a-navody/jak-spravne-nadepsat-zasilku

Conclusive enough for me.

Stop duplicating the postal code prefix in the format

If the postal code prefix is already declared ("postprefix"), there is no need to also have it in the format string ("fmt").

Postal code prefixes are usually appended only for international mail, so not having the prefix in the format string would allow a formatter to choose when to add the prefix (for international, but not domestic sending, etc).

Naming of Islas Baleares (Spanish province)

"Islas Baleares" should be "Balears".

The wikipedia page says "Islas Balears" is the name of the community (ES-IB), while the province (ES-PM) is called just "Baleares" or "Balears".
"Baleares" is the spanish name, "Balears" is the Catalan name.

The ISO newsletter lists "Balears" as the new name of the province, and it matches the examples of Alicante, Lleida, Girona (where the dataset uses the Catalan and not the Spanish names).
UPU still uses the Spanish name.

http://www.upu.int/fileadmin/documentsFiles/activities/addressingUnit/espEn.pdf
https://en.wikipedia.org/wiki/ISO_3166-2:ES
http://www.iso.org/iso/iso_3166-2_newsletter_ii-1_corrected_2010-02-19.pdf

Note: There was an argument from a Spanish user that both the Catalan and Spanish names should be used where they exist ("Baleares / Balears", "Girona / Gerona") for UX purposes. I'm not sure how much it makes sense, but it's worth mentioning.

address metadata in countryinfo.txt appears different compared to what the address data service returns

https://github.com/googlei18n/libaddressinput/blob/master/testdata/countryinfo.txt


Example 1

http://i18napis.appspot.com/address/data/AE
returns

{"lang": "ar", "sub_lnames": "Abu DhabiFujairahUmm Al QuwainSharjahDubaiRas al KhaimahAjmān", "name": "UNITED ARAB EMIRATES", "require": "AS", "state_name_type": "emirate", "id": "data/AE", "languages": "ar", "lfmt": "%N%n%O%n%A%n%S", "sub_keys": "أبو ظبيالفجيرةام القيوينإمارة الشارقةّإمارة دبيّإمارة رأس الخيمةعجمان", "key": "AE", "sub_isoids": "AZFUUQSHDURKAJ", "fmt": "%N%n%O%n%A%n%S"}

countryinfo.txt:
data/AE={"id":"data/AE","key":"AE","name":"UNITED ARAB EMIRATES","fmt":"%N%n%O%n%A%n%C","require":"AC"}


Example 2

http://i18napis.appspot.com/address/data/HK

{"lang": "zh-hant", "upper": "S", "sub_lnames": "KowloonHong Kong IslandNew Territories", "name": "HONG KONG", "sub_mores": "truetruetrue", "require": "AS", "state_name_type": "area", "id": "data/HK", "languages": "zh-hanten", "lfmt": "%N%n%O%n%A%n%C%n%S", "sub_keys": "九龍香港島~新界", "key": "HK", "locality_name_type": "district", "fmt": "%S%n%C%n%A%n%O%n%N"}

countryinfo.txt

data/HK={"id":"data/HK","key":"HK","name":"HONG KONG","lang":"zh-hant","languages":"zh-hanten","fmt":"%S%n%A%n%O%n%N","lfmt":"%N%n%O%n%A%n%S","require":"AS","upper":"S","state_name_type":"area","sub_keys":"九龍香港島新界","sub_lnames":"KowloonHong Kong IslandNew Territories","sub_mores":"falsefalse~true"}

Differences:
fmt/lfmt values are missing %C
sub_mores values are different
locality_name_type key is missing


Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.