Skip to Main Content U.S. Department of Energy
 

Using MIF Transformers

A Transformer converts from one data type to another. It is attached to an inbound or outbound endpoint on a module or component. This encourages code re-usability by providing a standard way to perform data transformations between components which may not have been originally designed to work together.

Pre-exising or novel transformers can be used – several common transformers are included with MIF. To create a new Transformer, you must create a class which extends the class AbstractMifTransformer.

This document explains our transformer sample code and describes how to create a MIF Transformer:

  • Example description
  • Running the example
  • Creating a transformer class

Example Overview

This example builds on the Hello World Example by adding a transformer to each module. A transformer is added to the inbound data path on the first module and the outbound path on the second module to demonstrate that a transformer can be set on an inbound or outbound endpoint.

Transformer Diagram

The two modules in this example perform similar functions as in the hello example. However, both modules in this example accept and return byte arrays. So, the way the example operates is as follows: The user enters his/her name when prompted and the name is sent as a String to the first module, ByteNameModule. When the name arrives at this module, the first transformer – StringToBytes – is called, which converts the name from a String to a byte[] representation. The StringToBytes transformer is a pre-defined transformer object available to the MIF Programmer. In this case, the programmer does not have to create his own transform. The ByteNameProcessor contatenates the byte name with another byte array and returns this byte array to the next module, ByteHalModule.

The processor wrapped by ByteHalModule concatenates another byte array with the received one and returns the new data. As the data exits the module, the second transformer – BytesToHalData – is called which converts the array of bytes to a user-defined data type, HalData. This object simply a string plus a timestamp. In this case, we implemented our own transformer to handle the data conversion. When HalData object returns to the user, it is printed to the console via its toString() method.

Running the example

Note: $MIF_HOME refers to the MIF installation directory

Follow these steps:

  • Open a shell, navigate to $MIF_HOME/bin
  • Execute the following
run-mif.bat -c gov.pnnl.mif.samples.helloTransformer.HelloTransformerDriver
  • Enter a name when prompted.
  • The console output will then look like:
Enter name:Dave
ByteNameProcessor: 72 101 121 44 32 68 97 118 101 
ByteHalProcessor: 72 101 121 44 32 68 97 118 101 44 32 119 104 97 116 32 97 114 101 32 121 111 117 32 100 111 105 110 103 63 
Hey, Dave, what are you doing? [2007-09-21 16:23:10.263]

The output shows the name as entered by the user, the bytes being sent from each module, and the HalData object received by the client and printed by the toString() method.

Code walkthrough

Constructing the pipeline

All the source files for this example can be found in $MIF_HOME/samples/guide/helloTransformer. The code is very similar to the hello world example. The differences in the two examples are shown below.

The pipeline and endpoints for the first module are created as in helloWorld. Then a StringToBytes transformer (included in the MIF API) is created using the pipeline object and added to the inbound endpoint on the first module:

MifEndpoint inNameEndp = pipeline.addMifEndpoint("inNameEndp", EndpointType.STREAM, "console.in?promptMessage=Enter name: ");
AbstractMifTransformer stringToBytes = pipeline.addSiftTransformer( new StringToByteArray() );
inNameEndp.setTransformer(stringToBytes);

Then, the ByteToHalData transformer is created, added to the pipeline, and set on the outbound transformer of the second module:

MifEndpoint outHalEndp = pipeline.addMifEndpoint("outHalEndp", EndpointType.STREAM, "console.out");
AbstractMifTransformer bytesToHalData = pipeline.addSiftTransformer( new BytesToHalData() );
outHalEndp.setTransformer(bytesToHalData);

The ByteToHalData transformer had to be created for this example. This is the case for many application-specific transformers. In the following section, we demonstrate how to create such a transformer.

Creating the custom transformer

To create a custom transformer, we need to extend the AbstractMifTransformer class. This class has one abstract method:

public abstract Object transformIt(Object objToTransform);

The argument objToTransform is the object being received on the endpoint. This method's job is to convert this object to the desired type, then return the transformed object. Here is the implementation:

public class BytesToHalData extends AbstractMifTransformer {

  public Object transformIt(Object objToTransform) {
    byte[] bytes;
    HalData halData = null;
	
    // Make sure we received the expected type
    if (objToTransform instanceof byte[]) {
      bytes = (byte[]) objToTransform;
      // Do the conversion
      halData = new HalData( new String(bytes), new Timestamp(System.currentTimeMillis()) );
    }
    else {
      System.err.println("Object not of type byte[]");
    }
	
    return halData;
  }
}

Once the transformed object is returned, it is passed on to the next stage in the pipeline as normal.

 
using_transformers.txt · Last modified: 2008/11/20 20:26 by d3l021