Featured Post

Applying Email Validation to a JavaFX TextField Using Binding

This example uses the same controller as in a previous post but adds a use case to support email validation.  A Commons Validator object is ...

Saturday, April 2, 2011

Component Field TABLE in Talend Open Studio

A TABLE parameter provides a Talend custom component with a flexibile mechanism for retrieving repeated groups of information during configuration.
 When configuring a Talend component, a user can be presented with a TABLE along with add/remove buttons for defining a varying structure.  For example, tReplace uses a TABLE parameter to gather lists of replacement commands from the user.  The list of replacement commands isn't subject to a limit.  Also, tReplace defines a replacement command as a column, search string, replacement, matching attributes, and  a comment.

Component View
 
The following screenshot is from a component called tRules. tRules accepts a list of expressions from the user along with annotations that will be output if an expression fails.  The list of expressions is defined as (expression, reason code, reason message).  'expression' is the Javascript expression to evaluate.  "reason code" and "reason message" are user-provided annotations output to the reject file if the expression fails.

Component with PARAMETER FIELD="TABLE"
XML Descriptor
 
This is the XML descriptor supporting the above screenshot.  A PARAMETER called RULES of FILE "TABLE" contains a nested structure of ITEMS.  Each child ITEM is a NAME/VALUE pair that defines a column and a default value in the table.

XML Descriptor Showing PARAMETER with FIELD="TABLE"
Properties
 
The TABLE is supported by a set of message properties.  The message properties define an overall header (RULES.NAME) and column headers (RULES.ITEM.EXPRESSION, RULES.ITEM.REASON_CODE, RULES.ITEM.REASON_MESSAGE).

RULES.NAME=Rules
RULES.ITEM.EXPRESSION=Java Expression
RULES.ITEM.REASON_CODE=Reason Code
RULES.ITEM.REASON_MESSAGE=Reason Message

Code
 
Using the TABLE values entered by the user is a little different than the simpler FIELDS that produce strings.  The TABLE contents are accessed using the getObjectValue() method in ElementParameterParser.   getObjectValue() -- in this case -- will return a List of Map records where each row in the Component View is a Map.  The aggregate is a List.

This will require a cast, preferably using Java Generics.  Additionally, you'll work with the TABLE's contents in a loop.  Here is an example main for FIELD="TABLE".


<%@ jet
imports="
org.talend.core.model.process.INode
org.talend.core.model.process.ElementParameterParser
org.talend.core.model.metadata.IMetadataTable
org.talend.core.model.metadata.IMetadataColumn
org.talend.core.model.process.IConnection
org.talend.core.model.process.IConnectionCategory
org.talend.designer.codegen.config.CodeGeneratorArgument
org.talend.core.model.metadata.types.JavaTypesManager
org.talend.core.model.metadata.types.JavaType
java.util.List
java.util.Map
"
%>
<%
CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
INode node = (INode)codeGenArgument.getArgument();
String cid = node.getUniqueName();

List<Map<String,String>> rules=
(List<Map<String,String>>)ElementParameterParser.getObjectValue(node, "__RULES__");
%>
<%
for( Map<String, String> rule : rules ) {

String expression = rule.get("EXPRESSION");
String reasonCode = rule.get("REASON_CODE");
String reasonMessage = rule.get("REASON_MESSAGE");

%>
System.out.println( "testing expression=<%= expression %>" );
System.out.println( "if fail, reasonCode=<%= reasonCode %>" );
System.out.println( "if fail, reasonMessage=<%= reasonMessage %>" );
<%
}
%>

Notice that the System.out.println() calls are not within the JSP-style braces.  This can lead to a problem if the expression, reasonCode, or reasonMessage variables contain quote which will break the println() calls.

It's easy to add a very flexible control to Talend that gathers structured and repeated component configuration data from the user.  Use a PARAMETER of FIELD="TABLE" to define a set of records created by the user without bounds.  Cast this using getObjectValue(), rather than using only the String value from getValue().



1 comment:

  1. Hey Carl, Thanks for the post!
    Is there a way to provide default value for a parameter having field type as table?

    ReplyDelete