Package org.gs1.gs1encoders


package org.gs1.gs1encoders

GS1 Barcode Syntax Engine - Java wrapper.

The GS1 Barcode Syntax Engine provides routines that support the processing of GS1 syntax data, including Application Identifier element strings and GS1 Digital Link URIs, whether these are provided in raw or human-friendly format or as normalised scan data received from barcode readers.

The implementations are intended for use with GS1 standards and applications and do not contain additional features that might be required for more general use.

Within the GS1 Application Identifier system, structured data is represented in different formats depending upon the context.

The data formats supported by this library are:

  • Bracketed AI element strings: Human-friendly rendition of AI data as a single string using numerical AIs.
  • Unbracketed AI element strings: Rendition of AI data that corresponds most directly to encoded barcode data.
  • GS1 Digital Link URIs
  • Scan data: The expected result of scanning a symbol with a barcode reader that has AIM symbologies identifiers enabled.
  • Human Readable Interpretation (HRI): Human-friendly redition of the AI data contained within a symbol. This may also include Data Titles to present the AI data in the form of "mixed HRI/non-HRI text". (Output only.)

The following diagram shows how the library can be used for processing and transformation of GS1 data, indicating which formats are accepted as input, how barcode message data is generated and AI data extracted from the provided input data, and how the given data can be output in various formats.

Data transformation: Inputs, outputs and buffers

The above diagram highlights that conceptually the library contains two internal "data buffers":

  • Barcode message buffer: This is populated with the raw message that would be borne by a GS1 barcode symbol that represents the input data, e.g. unbracketed AI syntax with FNC1 in first for regular AI element strings; plain string for a plain data or a GS1 Digital Link URI.
  • Extracted AI buffer: This contains the in-order AI data that was extracted from the input data.

The main operations of the library involve reading and updating the state of these buffers.

Quick start

To use the library you must first build the wrapper for your platform.

Building the Java wrapper

On Unix/macOS:
  1. First, compile the C library as a static library:
     make -C src/c-lib -j `nproc` libstatic
     
  2. Then build the Java wrapper:
     ant -f src/java/build.xml
     
On Windows:
  1. First, build the C library using Visual Studio or from a Developer Command Prompt:
     msbuild src\gs1encoders.sln /t:gs1encoders /p:Configuration=Debug /p:Platform=x64
     
  2. Then build the Java wrapper:
     ant -f src\java\build.xml
     
This generates two files in src/java/:
  • libgs1encoders.jar - The Java class library
  • libgs1encodersjni.so (or .dll on Windows, .dylib on macOS) - The native JNI library
  • libgs1encoders.so symlink (or .dll on Windows, .dylib on macOS)

Running the example application

After building, you can test it by running the interactive example application:
 ant -f src/java/build.xml test
 
The example application provides an interactive menu for testing different input formats and features.

Using in Your Own Project

To use the wrapper in your Java project you must:
  1. Add libgs1encoders.jar to your project's classpath at compile time and runtime
  2. Ensure the directory containing the native library (libgs1encodersjni.so) and the symlink (libgs1encoders.so) are in java.library.path at runtime
For a minimal example a MyApp.java file as follows:
 import org.gs1.gs1encoders.*;

 public class MyApp {

     static {
         System.loadLibrary("gs1encodersjni");
     }

     public static void main(String[] args) {
         try {
             GS1Encoder gs = new GS1Encoder();
             System.out.println("GS1 Syntax Engine version: " + gs.getVersion());
             gs.free();
         } catch (Exception e) {
             System.err.println("Error: " + e.getMessage());
         }
     }
 }
 
Compile your application as follows:
 javac -classpath <path/to/libgs1encoders.jar> MyApp.java
 
Run your application as follows:
 java -classpath <path to libgs1encoders.jar>:. -Djava.library.path=<directory containing libgs1encoders{jni}.{so,dylib,dll}> MyApp
 
For a comprehensive example, see Example.java.

Android Mobile App Quick Start

To use the GS1 Barcode Syntax Engine in an Android application:
  1. Create a new Android project in Android Studio (File → New → New Project)
  2. Enable NDK support in app/build.gradle:
     android {
         ...
         externalNativeBuild {
             cmake {
                 path file('src/main/cpp/CMakeLists.txt')
                 version '3.22.1'
             }
         }
     }
       
  3. Create symlinks to the Java and C library source:
     cd app/src/main/java/org/gs1
     ln -s ../../../../../../../path/to/gs1-syntax-engine/src/java/org/gs1/gs1encoders gs1encoders
    
     cd app/src/main/cpp
     ln -s ../../../../../path/to/gs1-syntax-engine/src/c-lib gs1encoders
       
  4. Create app/src/main/cpp/CMakeLists.txt:
     cmake_minimum_required(VERSION 3.22)
     project(gs1encoders)
    
     file(GLOB LIB_SOURCE_FILES
         gs1encoders/ai.c
         gs1encoders/dl.c
         gs1encoders/scandata.c
         gs1encoders/syn.c
         gs1encoders/gs1encoders.c
         gs1encoders/syntax/gs1syntaxdictionary.c
         gs1encoders/syntax/lint_*.c
     )
    
     add_compile_definitions(GS1_LINTER_ERR_STR_EN)
     add_library(gs1encoders SHARED ${LIB_SOURCE_FILES})
       
  5. In your Activity, load the native library and create an encoder instance:
     import org.gs1.gs1encoders.GS1Encoder;
    
     public class MainActivity extends AppCompatActivity {
    
         static {
             System.loadLibrary("gs1encoders");
         }
    
         @Override
         protected void onCreate(Bundle savedInstanceState) {
             super.onCreate(savedInstanceState);
             setContentView(R.layout.activity_main);
    
             GS1Encoder gs = new GS1Encoder();
             String version = gs.getVersion();
             setTitle("GS1 Encoders library: " + version);
             // Use gs to process barcode data...
         }
    
         @Override
         protected void onDestroy() {
             super.onDestroy();
             gs.free();
         }
     }
       
For a comprehensive Android app example with barcode scanning and full UI, see the GS1 Encoders Android App.

Example uses

The following are examples of how to use the library.

Unless otherwise specified, the getter methods return library-managed data that must not be modified by the user. If their content must persist following a subsequent call to the same instance of the library then they must be copied to a user-managed variable.

Most of the setter and action methods of this library throw exceptions in the event of failure. Production code should catch these exceptions and handle them appropriately, which might include rendering the error message to the user.

The following code processes AI data input, validates it (reporting any failures) and displays the extracted AIs if the validation succeeds.
 GS1Encoder gs = new GS1Encoder();                           // Create a new instance of the library

 // gs.setPermitUnknownAIs(true);                            // Uncomment only if it is necessary to handle AIs
                                                             // that are not known to the library

 // Input provided as a bracketed AI element string
 //
 try {
     gs.setAIdataStr("(01)12312312312333(10)ABC123(99)TEST");
 } catch (Exception e) {
     System.err.println("ERROR: " + e.getMessage());         // Display a descriptive error message
     String errMarkup = gs.getErrMarkup();
     if (!errMarkup.isEmpty())                               // Display the invalid AI in the case of a Linting failure
         System.err.println("Bad AI data: " + errMarkup);
     // Finally, handle the error in an application-specific way
     System.exit(1);
 }

 // Alternatively, the input may be given in the following formats:
 //
 // gs.setDataStr("^011231231231233310ABC123^99TEST");       // Unbracketed element string, "^" = FNC1
 //
 // gs.setDataStr("https://example.com/01/12312312312333/10/ABC123/99/TEST");   // GS1 Digital Link URI
 //
 // gs.setScanData("]Q1011231231231233310ABC12399TEST");   // Barcode scan data, containing a "GS" (ASCII 0x1D) separator

 for (String line : gs.getHRI()) {                           // Display the extracted AI data as HRI text
     System.out.println(line);
 }
 

Converting an AI element string to barcode message data

In this example we process a bracketed AI element string to convert it into barcode message data, suitable for carrying in a GS1 barcode symbol.
 GS1Encoder gs = new GS1Encoder();

 try {
     gs.setAIdataStr("(01)12312312312333(10)ABC123(99)TEST");    // Accept a bracketed AI element string
 } catch (Exception e) {
     // Handle error and return
 }

 System.out.println(gs.getDataStr());                        // Render the barcode message buffer
 

Note: The barcode message data read and emitted by this library uses a harmonised format that does not concern itself with internal encoding quirks of various symbologies. In the harmonised barcode message data:

  • A leading "^" always indicates GS1 Application Identifier syntax data, i.e. a notional FNC1 in first character position. (This is even true for DotCode in whose internal encoding the literal FNC1 non-data character may have an inverted meaning for certain messages depending upon their regular data content.)
  • A "^" at any other position represents a notional FNC1 non-data Application Identifier separator character. (This is even the case for QR Code in whose internal encoding a "%" character or "{GS}" character takes on the AI separator role typically assigned to the FNC1 non-data character, depending upon the effectuve encodation mode.)

Additionally, barcode image encoder libraries have differing conventions for how to input FNC1 characters, extending to whether it is necessary to be explicit about the notional FNC1 character in the first position when specifying a GS1 Application Identifier syntax symbol.

Consequently, the barcode message data emitted by this library may need to be post-processed to align to the specific requirements of whatever symbol generation library is in use.

Barcode scan data processing

In this example we process scan data from a barcode reader to extract the AI data.
 GS1Encoder gs = new GS1Encoder();

 // Disable validation of mandatory association between AIs if the symbol may
 // be one of multiple on a label
 gs.setValidationEnabled(Validation.RequisiteAIs, false);

 try {
     gs.setScanData("]Q1011231231231233310ABC12399TEST");
 } catch (Exception e) {
     // Handle error and return
 }

 for (String line : gs.getHRI()) {
     System.out.println(line);
 }

 // If it is necessary to know the "symbology" that was scanned then this can
 // be read using getSym(), however note the caveats given in the
 // description of setScanData()
 

Note: It is required that AIM Symbology Identifiers are enabled on the barcode reader, and that the scanned barcode message "survives the channel" intact, i.e. that no character substitutions have been made by the reader, in particular that any embedded FNC1 separator characters are correctly represented by GS characters (ASCII 29). If this is not the case then the scanned data should be pre-processed to meet this requirement.

  • Class
    Description
    Main class for processing GS1 barcode data, including validation, format conversion, and generation of outputs such as GS1 Digital Link URIs and Human-Readable Interpretation text.
    Recognised GS1 barcode formats ("symbologies") for processing scan data.
    Optional AI validation procedures that may be applied to detect invalid inputs.
    Custom error class for the wrapper for accessing the GS1 Barcode Syntax Engine native library from Java.
    Custom error class for the wrapper for accessing the GS1 Barcode Syntax Engine native library from Java.
    Custom error class for the wrapper for accessing the GS1 Barcode Syntax Engine native library from Java.
    Custom error class for the wrapper for accessing the GS1 Barcode Syntax Engine native library from Java.