Perl component creation, step by step

Now you have read the illustrated theory about component structure and TOS code generation model in the component creation guide, let's have a step by step component creation tutorial. An very simple component which prints a list of email addresses at each iteration in a row flow. We'll create the tTutorialRow. By convention, we name it Row because it works in row mode.

Component duplication

Appart from the very first component all components are created by duplicating the nearest component. For the tTutorialRow, we'll have a TABLE parameter type to handle a list of email addresses. The tRowGenerator takes a TABLE as input, let's duplicate this one!

At Talend, we use a shell script to duplicate a component : talend_duplicate_component.sh

#!/bin/bash
 
# usage : talend_duplicate_component.sh LogRow PerlRow
 
orig=$1
dest=$2
 
if [ -e t$dest ]
then
    echo "$dest already exists"
    exit 1
fi
 
if [ ! -e t$orig ]
then
    echo "$orig does not exist"
    exit 1
fi
 
# copie the original component
cp -r t$orig t$dest
 
# goes into new component
cd t$dest
 
# remove SVN specific file
rm -rf .svn
 
# rename files with new name
ls -d *$orig* \
  | perl -ne 'chomp; $old = $_; $new = $old; $new =~ s/'$orig'/'$dest'/; print "mv $old $new\n"' \
  | bash
 
# find and replace occurence of component name inside files
ls *.xml *.properties *.*jet \
  | xargs perl -pi -e 's/'$orig'/'$dest'/g'
 
cd -
echo "job's done"

We go to the components directory and we launch the script:

$ cd plugins/org.talend.designer.core_1.0.0.20061004-2013-V1/components
$ talend_duplicate_component.sh RowGenerator TutorialRow
job's done

Now we have a directory tTutorialRow with all required files inside it.

XML description

Open the tTutorialRow.xml file, keep only the FIELD=“TABLE” parameter, rename it to ADDRESSES, rename the first column to USERNAME and add another column DOMAIN. You should obtain:

<PARAMETERS>
  <PARAMETER NAME="ADDRESSES" FIELD="TABLE" REQUIRED="true" NUM_ROW="1" NB_LINES="5">
    <ITEMS CODE_LANGUAGE="perl">
      <ITEM NAME="USERNAME" />
      <ITEM NAME="DOMAIN" />
    </ITEMS>
  </PARAMETER>
</PARAMETERS>

You also have to tell TOS that youcan input 1 row link to the component.

<CONNECTOR CTYPE="FLOW" MAX_INPUT="1"/>

Labels

We want some default labels in the GUI. Open component.properties file, change the LONG_NAME to “Tutorial component”, remove entries specific to tRowGenerator, add the ADDRESSES table and its columns. You should obtain:

NAME=tTutorialRow
LONG_NAME=Tutorial component
FAMILY=Misc
HELP=org.talend.help.TutorialRow

ADDRESSES.NAME=Addresses
ADDRESSES.perl.ITEM.USERNAME=Username
ADDRESSES.perl.ITEM.DOMAIN=Domain

Template

Begin

<%@ jet 
package="org.talend.designer.codegen.translators" 
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.designer.codegen.config.CodeGeneratorArgument
    java.util.Map
    java.util.List
" 
class="TutorialRowStart" 
%>

<%
CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
INode node = (INode)codeGenArgument.getArgument();
boolean stats = codeGenArgument.isStatistics();

List<IMetadataTable> metadatas = node.getMetadataList();
if ((metadatas!=null)&&(metadatas.size()>0)) {
    IMetadataTable metadata = metadatas.get(0);
    if (metadata!=null) {
        String cid = metadata.getTableName();
        List<Map<String, String>> lines = (List<Map<String,String>>)ElementParameterParser.getObjectValue(node, "__ADDRESSES__");
%>

my @addresses_<%=cid %> = (
<%
  for (int i=0; i<lines.size(); i++) {
    Map<String, String> line = lines.get(i);
%>
    <%= line.get("USERNAME") %>.'@'.<%= line.get("DOMAIN") %>,
<%
  }
%>
);

my $line_number_<%=cid %> = 1;

<%
    }
}
%>

In the “lines” Java variable, we store all lines filled in the GUI. In the @addresses Perl array, we store concatenations of column USERNAME and column DOMAIN. The user is supposed to fill the table as illustrated in the following screenshot.

Addresses table filled

We also have a $line_number Perl scalar variable to know the current line number for this tTutorialRow.

Main

<%@ jet 
package="org.talend.designer.codegen.translators" 
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.designer.codegen.config.CodeGeneratorArgument
    java.util.Map
    java.util.List
" 
class="TutorialRowMain" 
%>

<%
CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
INode node = (INode)codeGenArgument.getArgument();
boolean stats = codeGenArgument.isStatistics();

List<IMetadataTable> metadatas = node.getMetadataList();
if ((metadatas!=null)&&(metadatas.size()>0)) {
    IMetadataTable metadata = metadatas.get(0);
    if (metadata!=null) {
        String cid = metadata.getTableName();
%>

print(
    sprintf('%05u', $line_number_<%=cid %>++),
    ': ',
    join(
         ',',
         @addresses_<%=cid %>
    ),
    "\n"
);

<%
    }
}
%>

As described in the section Perl code generation model”, the Perl output code of this template will be executed at each row iteration.

It will display the line number and the list of email addresses.

End

<%@ jet 
package="org.talend.designer.codegen.translators" 
imports="
    org.talend.core.model.process.INode 
    org.talend.core.model.metadata.IMetadataTable
    org.talend.designer.codegen.config.CodeGeneratorArgument
    java.util.List
" 
class="TutorialRowEnd"
%>

<%
CodeGeneratorArgument codeGenArgument = (CodeGeneratorArgument) argument;
INode node = (INode)codeGenArgument.getArgument();
boolean stats = codeGenArgument.isStatistics();

List<IMetadataTable> metadatas = node.getMetadataList();
if ((metadatas!=null)&&(metadatas.size()>0)) {
    IMetadataTable metadata = metadatas.get(0);
    if (metadata!=null) {
%>

# nothing to do right here

<%
    }
}
%>

As you can see, no real Perl code to output in this template part.

Component execution

Once the component described and templates written, restart TOS and see you new component in the Palette. Create a simple Job using tTutorialRow, with a tRowGenerator as input of 10 lines.

simple job using tTutorialRow

In my “run job” output, I have:

Starting job tutorial at 12:35 17/10/2006.
00001: foo@bar.com,bar@foo.com,foobar@barfoo.com
00002: foo@bar.com,bar@foo.com,foobar@barfoo.com
00003: foo@bar.com,bar@foo.com,foobar@barfoo.com
00004: foo@bar.com,bar@foo.com,foobar@barfoo.com
00005: foo@bar.com,bar@foo.com,foobar@barfoo.com
00006: foo@bar.com,bar@foo.com,foobar@barfoo.com
00007: foo@bar.com,bar@foo.com,foobar@barfoo.com
00008: foo@bar.com,bar@foo.com,foobar@barfoo.com
00009: foo@bar.com,bar@foo.com,foobar@barfoo.com
00010: foo@bar.com,bar@foo.com,foobar@barfoo.com
Job tutorial ended at 12:35 17/10/2006. [exit code=0]
 
doc/component_creation_example_perl.txt · Last modified: 2011/12/17 03:52 (external edit)
 
 
Recent changes RSS feed Driven by DokuWiki