Wednesday, June 23, 2010

Velocity Templates for Dynamic Transformations

We can take advantage of Velocity templates to apply dynamic transformations and create any kind of format for example CSV files. This is useful to perform dynamic mappings while importing feeds coming from different clients.

The below example shows how we can produce a list of the money spent in tips (15%) for a list of restaurants and the lunch prices. The source data is injected (merged) into the velocity template and the destination data is generated from the velocity template after applying dynamic rules.

Using a similar approach you can transform let us say an Excel feed into a CSV file that has any number of columns distributed in any desired order, calculated or not.

Furthermore as the example shows you can get the final output from Velocity in Java Objects so you can perform additional tasks like validations.

The java code:

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.ArrayList;

import org.apache.velocity.VelocityContext;

public class MapDemo {
public static void main(String[] args) throws Exception {

VelocityContext ctx = new VelocityContext();
ctx.put("math", new MathTool());

List inList = new ArrayList();
Map inMap = new HashMap();

inMap.put("a", "The Crab House");
inMap.put("b", "35.50");

inMap = new HashMap();
inMap.put("a", "Red Lobster");
inMap.put("b", "25.60");

ctx.put("inList", inList);

List outList = new ArrayList();
Map outMap = null;
List outHeaders = new ArrayList();

Writer writer = new StringWriter();
Velocity.mergeTemplate("./mapDemo.vm", ctx, writer );

String[] resultLines = writer.toString().split("[\\r\\n]");

int rowCount = 0;
for(String line : resultLines) {
if(line.trim().length() == 0){
String[] resultFields = line.split("\\|");
if(rowCount == 0){
for(String field : resultFields) {
//System.out.println("****" + field + "***");
if(resultFields.length != outHeaders.size()) {
throw new Exception("Line violates signature: '" + line + "'");
outMap = new HashMap();
int fieldCount = 0;
for(String field : resultFields) {
outMap.put(outHeaders.get(fieldCount), field.trim());
fieldCount ++;
rowCount ++;



The Velocity Template:

#foreach( $item in $inList )
$item.a|$item.b|$math.mul($item.b, .20)

How to run the program:
javac -cp velocity-1.6.4-dep.jar:velocity-tools-2.0.jar
java -cp .:velocity-1.6.4-dep.jar:velocity-tools-2.0.jar MapDemo

No comments: