Babelfish: CDR

The Babelfish CDR is a library for handling payloads associated with the Australian Consumer Data Right. It is currently being developed and maintained by Biza.io.

License

License

GroupId

GroupId

io.biza
ArtifactId

ArtifactId

babelfish-cdr
Last Version

Last Version

1.2.4
Release Date

Release Date

Type

Type

jar
Description

Description

Babelfish: CDR
The Babelfish CDR is a library for handling payloads associated with the Australian Consumer Data Right. It is currently being developed and maintained by Biza.io.
Project Organization

Project Organization

Biza Pty Ltd

Download babelfish-cdr

How to add to project

<!-- https://jarcasting.com/artifacts/io.biza/babelfish-cdr/ -->
<dependency>
    <groupId>io.biza</groupId>
    <artifactId>babelfish-cdr</artifactId>
    <version>1.2.4</version>
</dependency>
// https://jarcasting.com/artifacts/io.biza/babelfish-cdr/
implementation 'io.biza:babelfish-cdr:1.2.4'
// https://jarcasting.com/artifacts/io.biza/babelfish-cdr/
implementation ("io.biza:babelfish-cdr:1.2.4")
'io.biza:babelfish-cdr:jar:1.2.4'
<dependency org="io.biza" name="babelfish-cdr" rev="1.2.4">
  <artifact name="babelfish-cdr" type="jar" />
</dependency>
@Grapes(
@Grab(group='io.biza', module='babelfish-cdr', version='1.2.4')
)
libraryDependencies += "io.biza" % "babelfish-cdr" % "1.2.4"
[io.biza/babelfish-cdr "1.2.4"]

Dependencies

compile (14)

Group / Artifact Type Version
javax.validation : validation-api jar 2.0.1.Final
com.fasterxml.jackson.core : jackson-databind jar 2.10.1
com.googlecode.libphonenumber : libphonenumber jar 8.11.1
org.hibernate.validator : hibernate-validator jar [6.1.0,)
org.hibernate.validator : hibernate-validator-annotation-processor jar [6.1.0,)
javax.el : javax.el-api jar 3.0.0
org.glassfish.web : javax.el jar 2.2.6
org.apache.commons : commons-lang3 jar 3.9
commons-beanutils : commons-beanutils jar 1.9.4
commons-validator : commons-validator jar 1.6
io.swagger.core.v3 : swagger-core jar 2.1.1
ma.glasnost.orika : orika-core jar 1.5.4
io.github.classgraph : classgraph jar 4.8.60
com.opencsv : opencsv jar 5.1

provided (1)

Group / Artifact Type Version
org.projectlombok : lombok jar 1.18.10

test (3)

Group / Artifact Type Version
org.junit.jupiter : junit-jupiter-api jar 5.6.0-M1
org.junit.jupiter : junit-jupiter-engine jar 5.6.0-M1
org.slf4j : slf4j-simple jar 1.7.30

Project Modules

There are no modules declared in this project.

Babelfish CDR

Metapackage Conversion in Progress

NB: We are converting Babelfish CDR to a Metapackage with multiple components, some links might 404 at the moment

Maven Central Nexus Latest Snapshot Consumer Data Standards v1.2.0

develop build master build GitHub issues GitHub

The Babelfish CDR Library is a Java based Maven artifact for the efficient processing of JSON payloads associated with the Australian Consumer Data Right (aka open banking). It provides the ability to parse, manipulate, generate and validate compliant payloads associated with the Consumer Data Standards. It is annotated with industry standard Jackson and OpenAPI (fka Swagger) annotations to enable smooth integration into downstream projects.

Babelfish CDR is currently developed and maintained by Biza.io.

We welcome discussion around the Consumer Data Right at the DataRight.io Slack Channel.

Features

Quick Start

Processing an input payload and validating it is as simple as:

    ResponseBankingProductByIdV2 productResponse = new ObjectMapper().readValue(
        "{\"links\":{\"self\":\"http://localhost/cds-au/v1/banking/products/073e7e70-357d-4858-8f52-92283f4edd6f\"},\"meta\":{},"
        + "\"data\":{\"productId\":\"073e7e70-357d-4858-8f52-92283f4edd6f\",\"lastUpdated\":\"2020-02-03T06:32:27Z\","
        + "\"productCategory\":\"TRANS_AND_SAVINGS_ACCOUNTS\",\"name\":\"Example Product\",\"description\":\"Example Product Description\","
        + "\"brand\":\"ACME\",\"brandName\":\"ACME Bank\",\"isTailored\":false}}",
        ResponseBankingProductByIdV2.class);

Generating a compliant payload is as simple as:

    ResponseBankingProductByIdV2 productResponse =
        ResponseBankingProductByIdV2.builder()
            .links(LinksV1.builder().self(URI.create(
                "http://localhost/cds-au/v1/banking/products/073e7e70-357d-4858-8f52-92283f4edd6f"))
                .build())
            .meta(MetaV1.builder().build())
            .data(BankingProductDetailV2.builder().productId("073e7e70-357d-4858-8f52-92283f4edd6f")
                .lastUpdated(OffsetDateTime.now())
                .productCategory(BankingProductCategory.TRANS_AND_SAVINGS_ACCOUNTS)
                .name("Example Product").description("Example Product Description").brand("ACME")
                .tailored(false).build())
            .build();
    Set<ConstraintViolation<ResponseBankingProductByIdV2>> productResponseValidation =
        Validation.buildDefaultValidatorFactory().getValidator().validate(productResponse);
    if (productResponseValidation.isEmpty()) {
      System.out.println(new ObjectMapper().setSerializationInclusion(Include.NON_ABSENT).writeValueAsString(productResponse));
    } else {
      System.out.println(
          "Object failed validation with errors of: " + productResponseValidation.toString());
    }

Which yields:

{
   "data":{
      "productId":"073e7e70-357d-4858-8f52-92283f4edd6f",
      "lastUpdated":"2020-02-05T10:02:25.26832+11:00",
      "productCategory":"TRANS_AND_SAVINGS_ACCOUNTS",
      "name":"Example Product",
      "description":"Example Product Description",
      "brand":"ACME",
      "isTailored":false
   },
   "links":{
      "self":"http://localhost/cds-au/v1/banking/products/073e7e70-357d-4858-8f52-92283f4edd6f"
   },
   "meta":{

   }
}

Table of Contents

Usage

(Back to top)

This library is available on Maven Central and therefore can be utilised by adding the following lines to your pom.xml:

<dependency>
    <groupId>io.biza</groupId>
    <artifactId>babelfish-cdr</artifactId>
    <version>1.2.4</version>
</dependency>

Projects

babelfish-cdr is utilised in a number of public projects:

If you are using babelfish-cdr in your project drop us an email and we will add it here.

Support

Biza Pty Ltd are currently the primary maintainers of this software.

We welcome bug reports via GitHub Issues or if you prefer via email.

If you are looking for commercial support for this library please contact us via email.

Compatibility

(Back to top)

The Babelfish CDR library tries to provide full coverage of payloads defined within the Consumer Data Standards. While we try to align our version numbers to those of the Standards unfortunately the DSB has chosen to use all of the x.y.z versioning of the semantic versioning scheme. Consequently the following table outlines the alignment between Babelfish versions and the Standards:

Babelfish CDR Version Release Date CDS Spec Compatibility Notes Status
1.2.5-SNAPSHOT (current develop) Regular 1.2.0 Snapshot Development Release Active Development
1.2.4 (current stable) 2020-02-25 1.2.0 tag v1.2.4 Supported
1.2.3-SNAPSHOT 2020-02-25 1.2.0 Snapshot Development Release Deprecated
1.2.2 2020-02-12 1.2.0 tag v1.2.2 Deprecated
1.2.1-SNAPSHOT 2020-02-12 1.2.0 Snapshot Development Release Deprecated
1.2.0 2020-02-05 1.2.0 tag v1.2.0 Deprecated
1.0.0 2020-02-04 1.0.0 Initial Release, do not use Deprecated

Prerequisites

(Back to top)

You need the following installed and available in your $PATH during compilation:

  • Java 11+
  • Apache Maven 3.6.3 or later

Using Babelfish CDR in your project

(Back to top)

Babelfish CDR is intended for embedding within your CDR client or server project as a Maven (or Gradle) dependency. Once it is added to your project you gain access to the ability to manipulate CDR payloads in a number of different ways.

Parse and Validate CDR Payload

(Back to top)

Parsing a sample JSON payload can be conducted using Jackson and then verified using Java Validation API:

    ResponseBankingProductByIdV2 productResponse = new ObjectMapper().readValue(
        "{\"links\":{\"self\":\"http://localhost/cds-au/v1/banking/products/073e7e70-357d-4858-8f52-92283f4edd6f\"},\"meta\":{},"
        + "\"data\":{\"productId\":\"073e7e70-357d-4858-8f52-92283f4edd6f\",\"lastUpdated\":\"2020-02-03T06:32:27Z\","
        + "\"productCategory\":\"TRANS_AND_SAVINGS_ACCOUNTS\",\"name\":\"Example Product\",\"description\":\"Example Product Description\","
        + "\"brand\":\"ACME\",\"brandName\":\"ACME Bank\",\"isTailored\":false}}",
        ResponseBankingProductByIdV2.class);
    Set<ConstraintViolation<ResponseBankingProductByIdV2>> productResponseValidation =
        Validation.buildDefaultValidatorFactory().getValidator().validate(productResponse);

Validate and Generate CDR Payload

(Back to top)

Generating a CDR Payload can be conducted using the fluent builder API within Babelfish. Additionally the payload can be validated using Java Validation API.

An example is as follows:

ResponseBankingProductByIdV2 productResponse =
        ResponseBankingProductByIdV2.builder()
            .links(LinksV1.builder().self(URI.create(
                "http://localhost/cds-au/v1/banking/products/073e7e70-357d-4858-8f52-92283f4edd6f"))
                .build())
            .meta(MetaV1.builder().build())
            .data(BankingProductDetailV2.builder().productId("073e7e70-357d-4858-8f52-92283f4edd6f")
                .lastUpdated(OffsetDateTime.now())
                .productCategory(BankingProductCategory.TRANS_AND_SAVINGS_ACCOUNTS)
                .name("Example Product").description("Example Product Description").brand("ACME")
                .tailored(false).build())
            .build();
    Set<ConstraintViolation<ResponseBankingProductByIdV2>> productResponseValidation =
        Validation.buildDefaultValidatorFactory().getValidator().validate(productResponse);
    if (productResponseValidation.isEmpty()) {
      System.out.println(new ObjectMapper().setSerializationInclusion(Include.NON_ABSENT).writeValueAsString(productResponse));
    } else {
      System.out.println(
          "Object failed validation with errors of: " + productResponseValidation.toString());
    }

Convert CDR Payload between versions

(Back to top)

Babelfish enables you to convert between two different payload versions. This means that a Data Recipient can build for a newer (or older) version of a payload while maintaining ongoing compatibility from individual Data Holders who may be ahead or behind the version expected by the Recipient. We use Orika and a set of specific mappers for each different payload version and then make it available in BabelFishConverter.

An example is as follows:

    BankingProductDetailV2 detail = BankingProductDetailV2.builder()
        .productId("073e7e70-357d-4858-8f52-92283f4edd6f").lastUpdated(OffsetDateTime.now())
        .productCategory(BankingProductCategory.TRANS_AND_SAVINGS_ACCOUNTS).name("Example Product")
        .description("Example Product Description").brand("ACME").isTailored(false).build();

    // Downgrade it to V1
    BankingProductDetailV1 downgradedDetail =
        BabelFishConverter.convert(detail, BankingProductDetailV1.class);
    // Upgrade back to V2
    BankingProductDetailV2 upgradedDetail = BabelFishConverter.convert(downgradedDetail, BankingProductDetailV2.class);

Dynamically discover what class to use for version conversion

(Back to top)

To make it easier to integrate Babelfish into upstream projects we also make available the BabelfishVersioner class. Here's an example where we hand it a BankingProductDetailV2 and ask it for the nearest version (in this case the range is only 1 <= 2):

    Class<?> destinationType = BabelfishVersioner.getVersionedClass(inputData.getClass(),
        2, 1);
    BabelfishVersioner.convert(inputData, destinationType);

This is coupled in Deep Thought to allow for dynamic payload version switching based on request parameters (in CDRVersioner).

Using in Spring

(Back to top)

We are actively using Babelfish CDR payload descriptions within Deep Thought as part of a Spring + Springdoc project. The following demonstrates the definition of a Get Product Detail endpoint:

@Operation(summary = "Get Product Detail",
      description = "Returns details product information based on the specified product identifier")
  @ApiResponses(
      value = {
          @ApiResponse(responseCode = "200", description = "Response Successful",
              content = @Content(schema = @Schema(oneOf = {ResponseBankingProductByIdV1.class,
                  ResponseBankingProductByIdV2.class}))),
          @ApiResponse(responseCode = "404",
              description = "Unable to find requested Product Identifier")})
  @GetMapping(value = "/{productId}", produces = {MediaType.APPLICATION_JSON_VALUE})
  default ResponseEntity<ResponseBankingProductByIdV2> getProductDetail(
      @NotNull @Valid @PathVariable("productId") UUID productId) {
    return getDelegate().getProductDetail(productId);
  }

Extended Features

(Back to top)

Babelfish incorporates a number of customised features to aid developers with integrating with and using the CDR payloads.

Enumeration Labels

(Back to top)

All enumerations used within Babelfish provide a human readable label available via the label() method:

    System.out.println("name: " + BankingProductCategory.TRANS_AND_SAVINGS_ACCOUNTS.name()
        + " label: " + BankingProductCategory.TRANS_AND_SAVINGS_ACCOUNTS.label());
    // Result: name: TRANS_AND_SAVINGS_ACCOUNTS label: Transaction & Savings

JSON (De)Serialisators

(Back to top)

Babelfish employs a set of StdConverter extensions to facilitate the conversion to/from Common Field Types specified within the Standards. These are embedded as @JsonSerialize and @JsonDeserialize annotations within payloads but can be used independently if desired.

The following provides a table of the converters available:

Common Field Type CDS JSON Type Babelfish Java Type Serializer Deserializer
DateTimeString String OffsetDateTime OffsetDateTimeToDateTimeStringConverter DateTimeStringToOffsetDateTimeConverter
DateString String LocalDate LocalDateToStringConverter StringToLocalDateConverter
CurrencyString String Currency CurrencyToStringConverter StringToCurrencyConverter
RateString String BigDecimal BigDecimalToRateStringConverter RateStringToBigDecimalConverter
AmountString String BigDecimal BigDecimalToAmountStringConverter AmountStringToBigDecimalConverter
URIString String URI UriToUriStringConverter UriStringToUriConverter
ExternalRef (Country) String Locale CountryStringToLocaleConverter LocaleToCountryStringConverter
ExternalRef (Duration) String Duration StringToDurationConverter DurationToStringConverter
ExternalRef (Period) String Period StringToPeriodConverter PeriodToStringConverter
ExternalRef (MCC) String MerchantCategoryCodeType StringToMerchantCategoryCodeConverter MerchantCategoryCodeToStringConverter
ExternalRef (APCA Number) String ApcaNumberType StringToApcaNumberConverter ApcaNumberToStringConverter
ExternalRef (SWIFT Routing) String SwiftBicType StringToSwiftBicConverter SwiftBicToStringConverter
Base64 String (Base64) String StringToBase64StringConverter Base64StringToStringConverter

Custom Assertions

(Back to top)

Many of the payloads contain a custom javax.validation.Constraint called AssertTrueBabelfish.

AssertTrueBabelfish behaves like the default AssertTrue validation assertion but includes an additional String[] array called fields which provides information about the specific field(s) which were involved within a failure of the assertion. This annotation is used extensively for validating CDR payloads which utilise the additionalValue conditional field structure and are intended to provide human presentable error messages along with a pointer to the field(s) in question.

One such example is in BankingConstraintV1 which verifies that when a Constraint Type of MIN_BALANCE is specified the additionalValue field must be in CDS AmountString format.

Another notable example demonstrating compound reporting is within BankingProductFeeV1

  @AssertTrueBabelfish(
      message = "One of amount, balanceRate, transactionRate or accruedRate is MANDATORY",
      fields = {"amount", "balanceRate", "accruedRate", "transactionRate"})

This assertion reports a set of field names which can be highlighted but for which only one at a time is accepted.

Phone Number Parsing

(Back to top)

The CommonPhoneNumberV1 class contains a number of additional functions using Google's PhoneNumberUtil library. Most notably there is a method of setWithFullNumber which accepts a standard Australian number (for example 0733006000) and internationalises it into the requested format and fields. Use of this extension functionality is entirely optional.

Building

(Back to top)

babelfish-cdr uses Maven for compilation activies.

To build the library and install it in your local Maven cache:

  1. cd babelfish-cdr
  2. mvn clean install

Contributing

(Back to top)

  1. Clone repository and create a new branch: $ git checkout https://github.com/bizaio/babelfish-cdr -b my_new_branch
  2. Make changes (including tests please!)
  3. Submit Pull Request for integration of changes

License

(Back to top)

GNU Lesser General Public License v3.0 2020 - Biza Pty Ltd. Please have a look at the LICENSE.md for more details.

io.biza

Biza•io

Versions

Version
1.2.4
1.2.2
1.2.0
1.0.0