Java Reference

Regions

Introduction

Some countries report temperatures in Celsius, while others use Fahrenheit. Some format dates as month/day/year, while others prefer day/month/year. Some format times as 12-hour AM/PM, while others prefer a 24-hour clock. Some areas within a country have different RFID frequency ranges. Some jurisdictions define different ways to display nutrition data.

To make application development easier, KOS encapsulates these types of differences into data objects know as "Regions". This app note explains how to build and use regions.

Basics

This app note features the BaseRegion and XmlRegionFactory classes. It demonstrates how to extend these two class to create all your region-specific data. Let’s take a look at some basics first before getting to the actual example code.

Region data

The KOS BaseRegion class contains the following built-in properties:

id

A string that uniquely identifies a region. For example, "canada", "us-west", or "italy".
The only built-in region is named "factory", which is used internally as the system boots up.

country

A two- or three-letter ISO country code as defined in this Wikipedia page. For example, "US" or "GBR".

dateFormatId

ID of default date format. For example, "d_ddMMyy", "d_MMddyy", and "d_yyyyMMdd", which correspond to the built-in date format classes D_ddMMyy, D_MMddyy, and D_yyyyMMdd. You can also create custom date formats.

timeFormatId

ID of default time format. For example, "t_HHmm" and "t_hhmma", which correspond to the built-in time format classes T_HHmm and T_hhmma. You can also create custom time formats.

unitSystemId

ID of default unit system. For example, "si" and "us" come as built-in unit systems. And of course, you can create your own unit system.

Later, we’ll add our own custom fields by extending this class.

Unit systems

Let’s look at the two built-in unit systems provided by KOS: "SI" (the International System of Units, commonly known as the metric system) and "US" (the customary/standard United States system).

Table 1. Comparison of SI and US unit systems
Quantity SI units US units

mass/weight

grams

ounces

pressure

bars

psi

tempature

degrees Celsius

degrees Fahrenheit

volume

milliliters

fluid ounces

Write Code

This section shows a typical region.xml file along with region and XML-retrieval classes.

0) Define the problem

In your application you will almost certainly want to add custom region properties. In our example, we add two:

rfidFreq

RFID frequency for this region.

techSupport

Telephone number to receive technical support.

We’ll also handle three different regions: one for the Eastern US, one for the Western US, and one for the United Kingdom.

1) Create XML data

The following XML file defines our three regions. Note that it also contains the required "factory" region, which gets loaded with internal defaults. This file is typically located in a Java applications "resources" directory.

regions.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<regionDefs>
    <regions>
        <region id="factory"/>
        <region id="us-east">
            <country>USA</country>
            <unitSystemId>us</unitSystemId>
            <timeFormatId>t_hhmma</timeFormatId>
            <dateFormatId>d_MMddyy</dateFormatId>
            <rfidFreq>123.456</rfidFreq>
            <techSupport>+1-888-555-1234</techSupport>
        </region>
        <region id="us-west">
            <country>USA</country>
            <unitSystemId>us</unitSystemId>
            <timeFormatId>t_hhmma</timeFormatId>
            <dateFormatId>d_MMddyy</dateFormatId>
            <rfidFreq>456.123</rfidFreq>
            <techSupport>+1-877-555-1234</techSupport>
        </region>
        <region id="united-kingdom">
            <country>GBR</country>
            <unitSystemId>si</unitSystemId>
            <timeFormatId>t_HHmm</timeFormatId>
            <dateFormatId>d_yyyyMMdd</dateFormatId>
            <rfidFreq>888.999</rfidFreq>
            <techSupport>+44 20 1234 5678</techSupport>
        </region>
    </regions>
</regionDefs>

2) Extend BaseRegion class

Now that we have our region data, we need a data class to hold its information. To do that, we’ll create a custom region bean that extends BaseRegion.

Our custom Region bean
package com.example.regions;

import com.tccc.kos.core.service.region.BaseRegion;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter @Setter @ToString(callSuper = true)
public class Region extends BaseRegion {
    private double rfidFreq;     // RFID frequency
    private String techSupport;  // technical support phone number
}

The BaseRegion class contains the following properties:

  • String id; // unique ID of this region

  • String country; // ISO country code

  • String timeFormatId; // ID of default time format

  • String dateFormatId; // ID of default date format

  • String unitSystemId; // ID of default unit system

As you can see, this is quite simple:

  1. Extend the BaseRegion class

  2. Define any new fields

  3. Add boilerplate getters and setters using Lombok

3) Extend XmlRegionFactory class

Now that we have a place to hold our data, how does it get populated?

This is accomplished by extending the XmlRegionFactory and overriding two methods:

The custom XmlRegionFactory class
package com.example.regions;

import com.tccc.kos.commons.xml.XmlUtil;
import com.tccc.kos.core.service.region.BaseRegion;
import com.tccc.kos.core.service.region.XmlRegionFactory;
import org.jdom2.Element;

public class RegionFactory extends XmlRegionFactory {

    public static final String XML_RFID_FREQ = "rfidFreq"; (1)
    public static final String XML_TECH_SUPPORT = "techSupport";

    @Override
    public Region newRegion() { (2)
        return new Region();
    }

    @Override
    public void parseRegion(BaseRegion baseRegion, Element element) { (3)
        super.parseRegion(baseRegion, element); (4)
        if (baseRegion.isFactory()) { (5)
            return;
        }
        Region region = (OurRegion)baseRegion; (6)
        region.setRfidFreq(XmlUtil.getDouble(element, XML_RFID_FREQ, 0, true));
        region.setTechSupport(XmlUtil.getStr(element, XML_TECH_SUPPORT, null, false));
    }
}
1 Define the names of the two new fields.
2 Override the newRegion() method, returning a new instance of our customized region.
3 Override the parseRegion() method.
4 Call the super method to fill in the built-in values.
5 If region is the special "factory", then we’re done.
6 Cast the BaseRegion to Region, then grab our custom fields.

4) Create RegionModule class

Add the following class:

RegionModule class
package com.example.regions;

import com.example.Module;
import com.example.MyKosApp;
import com.tccc.kos.commons.core.context.BeanContext;
import com.tccc.kos.commons.core.context.annotations.Autowired;
import com.tccc.kos.commons.util.resource.ClassLoaderResourceLoader;
import com.tccc.kos.core.service.region.BaseRegion;
import com.tccc.kos.core.service.region.RegionService;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RegionModule implements Module {

    @Autowired
    private RegionService regionService;

    @Override
    public void init(BeanContext ctx) {
        log.info("> RegionModule.init()");

        // Load regions from XML:
        RegionFactory factory = new RegionFactory();
        factory.addLoader(new ClassLoaderResourceLoader(getClass().getClassLoader()));
        factory.load("regions.xml");

        // Install regions:
        MyKosApp myKosApp = ctx.getBean(MyKosApp.class);
        myKosApp.installRegions(factory.getRegions());
    }

    @Override
    public void run() {
        log.info("> RegionModule.run()");
        for (BaseRegion baseRegion : regionService.getRegions()) {
            Region region = (Region)baseRegion;
            regionService.setActiveRegion(baseRegion);
            logRegion(region);
        }
    }

    private void logRegion(Region region) {
        log.info("> regionId     : {}", region.getId());
        log.info("> country      : {}", region.getCountry());
        log.info("> unitSystemId : {}", region.getUnitSystemId());
        log.info("> dateFormatId : {}", region.getDateFormatId());
        log.info("> timeFormatId : {}", region.getTimeFormatId());
        log.info("> rfidFreq     : {}", region.getRfidFreq());
        log.info("> techSupport  : {}", region.getTechSupport());
    }
}

Run Tests

Run this KOS app in debug mode and view its log output. It should look something like:

RegionModule output
> ====== BEGIN =========================================
> MyKosApp.load()
> RegionModule.init()
> MyKosApp.start()
> RegionModule.run()

> regionId     : factory
> country      : null
> unitSystemId : si
> dateFormatId : d_yyyyMMdd
> timeFormatId : t_HHmm
> rfidFreq     : 0.0
> techSupport  : null

> regionId     : us-east
> country      : USA
> unitSystemId : us
> dateFormatId : d_MMddyy
> timeFormatId : t_hhmma
> rfidFreq     : 123.456
> techSupport  : +1-888-555-1234

> regionId     : us-west
> country      : USA
> unitSystemId : us
> dateFormatId : d_MMddyy
> timeFormatId : t_hhmma
> rfidFreq     : 456.123
> techSupport  : +1-877-555-1234

> regionId     : united-kingdom
> country      : GBR
> unitSystemId : si
> dateFormatId : d_yyyyMMdd
> timeFormatId : t_HHmm
> rfidFreq     : 888.999
> techSupport  : +44 20 1234 5678
> ====== END ===========================================

Summary

In this app note, we learned how to extend the built-in BaseRegion and XmlRegionFactory classes, which gives us the ability to easily handle regional differences. This ensures that our application can be used in multiple places around the world with minimum developer effort.

Previous
Next
On this page
Java Development
Seamlessly transition from Legacy+ systems to Freestyle microdosing and advanced distributed dispense systems.
UI Development
Using KOS SDKs, integrating Consumer and Non-consumer facing UIs becomes seamless, giving you less hassle and more time to create.
Video Library
Meet some of our development team, as they lead you through the tools, features, and tips and tricks of various KOS tools.
Resources
Familiarize yourself with KOS terminology, our reference materials, and explore additional resources that complement your KOS journey.
Copyright © 2024 TCCC. All rights reserved.