I want to generate some java code using freemarker, that is to generate parameters for a method.Say I have a method named doIt, which needs some parameter name and their class names, I will give the template a param named paramList.I define a macro directive , iterate the parameters list,but consequently each parameter occupies a row. My template code is as below:
<#macro paramList plist>
<#if plist??>
<#list plist as p>
${p.javaType?substring(2)} ${p.name} <#if p_has_next>, </#if>
</#list>
</#if>
</#macro>
doIt(<#paramList plist=params/>)
The running result is :
doIt( int end ,
String endDate ,
String evtCode ,
int evtNo ,
String giftCode ,
int start ,
String startDate
)
How to make all the parameters output appear in the same row. I know I can write the list directive logic in the same row to avoid line breaking ,but if there are other logic too, it will get too long to read and understand after a while.
The format I want is :
doIt(int end , String endDate, String evtCode , int evtNo , String giftCode , int start , String startDate)
Put a <#t> after the innermost </#if>. (See http://freemarker.org/docs/ref_directive_t.html#ref.directive.t)
Another way for you to do it there would be to change your code like this:
<#macro paramList plist>
<#if plist??>
<#list plist as p>${p.javaType?substring(2)} ${p.name} <#if p_has_next>, </#if></#list>
</#if>
</#macro>
doIt(<#paramList plist=params/>)
That is, make the list all inline. It's harder to read, but it will keep your white space characters that you need (i.e. the spaces).
Related
I'm using a data-directive or list to pull in several values, of which, I don't know how many there will be, and I want to try and list through them, and create several variables in the list if you will.
<#list 1..10 as x>
<#-- the next line doesn't work, but what i'm trying to fix -->
<#assign .vars['VAR'+x?string] = rand(100) />
</#list>
But I can list them back out that way.
<#list 1..10 as x>
${.vars['VAR'+x?string]}
</#list>
The documentation for assign, says:
name: name of the variable. It is not expression. However, it can be
written as a string literal, which is useful if the variable name
contains reserved characters, for example <#assign "foo-bar" = 1>.
Note that this string literal does not expand interpolations (as
"${foo}").
Is there no way around this? Am I trying to do the impossible? Is there some way I can insert a derived name into the .vars... Hash is it?
A little more research that was close, but didn't get me there:
This prevoius question gives how to READ the derived variable, but I need to WRITE/CREATE the derived variable.
FreeMarker get variable value by concatenating another variable value
This prevoius question shows that I can use a string to assign a variable and re-iterates what we saw in the first link.
Variable name in Freemarker Template Language
As FreeMarker can't assign to elements of collections (but you can ?map(it -> ...) a collection to another), the only way is via ?interpret:
<#list 1..10 as x>
<#-- the next line doesn't work, but what i'm trying to fix -->
<#'<#assign VAR${x?c} = rand(100)>'?interpret />
</#list>
I wonder why do you need to assign to a dynamically named variables though, since reading dynamically named variables is also a pain, even if a lesser one.
Ultimately, I believe the correct way to phrase my solution was a sequence of hashes:
<#list 1..z_Coupon_Pet.NUM_COUPONS as x>
<#assign INSTORE_COUPON=call_coupon_from_table1() />
<#assign ONLINE_COUPON=call_coupon_from_table2() />
<#assign coupon_string_row= '{
"COUPON_NUM" : ${x},
"INSTORE" : "${INSTORE_COUPON?js_string}",
"ONLINE" : "${ONLINE_COUPON?js_string}"
}' />
<#if x==1>
<#assign coupon_hash_string = coupon_string_row />
<#else>
<#assign coupon_hash_string = coupon_hash_string + ',' + coupon_string_row />
</#if>
</#list>
</#if>
<#if coupon_hash_string?has_content>
<#assign coupon_hash=parsejson('[' + coupon_hash_string + ']') />
</#if>
We specifically avoid <#assign my_hash = my_hash + element /> because of this note in the documentation:
Note that hash concatenation is not to be used for many repeated concatenations, like for adding items to a hash inside a loop. While adding together hashes is fast and is constant time (independent of the size of the hashes added), the resulting hash is a bit slower to read than the hashes added together. Thus after tens... of additions the result can be impractically slow to read.
I am working on looping through one object with multiple attributes. In my scenario, I am looking for external content values.
email_address
article01
article02
article03
email#address.com
Y
Y
These values can change all the time, so we have to define them manually every instance where we use this, but I want to be able to list them in a sequence and then loop through and include them when object.attribute=Y.
The below block is purely conceptual, but referencing the attribute within the expression is where I get confused.
<#assign seq = ['article01','article02','article03']>
<#list seq as articles>
<#if base.${article}="Y">
<#include "*/${article}.htm"/>
</#if>
</#list>
In this instance, the resulting code would be:
<html><article01.html content></html>
<html><article03.html content></html>
Assuming base.articel01 would work, you can use base[article] (instead of base.${article}).
I'm having trouble while trying to assign value to a variable using Freemarker.
<#if size??>
<#assign num=size?number>
<#if (num>0)>
<#list 0..num-1 as i>
<#if .vars['abc'+i?c] = "test">
<#assign .vars['abc'+i?c] = .vars['abc'+i?c]?replace("test","Test")>
</#if>
</#list>
</#if>
This is the error message: Encountered ".", but was expecting one of:
STRING_LITERAL
RAW_STRING
ID
Can anyone help me with this?
Thank you.
You can only write top-level variables in a FreeMarker template. Also you can't assign to a variable with dynamically constructed name, except with an ?interpret hack: <#"<#assign abc${i?c} = abc${i?c}?reaplce('test', "Test")>"?interpret />. Obviously that's horrid... BTW, what's the use case here? Why do you need to assign to dynamically constructed variable names?
<#assign reasonValue="xxx.ftl">
and I call it like:
<#include "${reasonValue}">
and I get output like:
Rejected - Something
how can I now use split on this ouput because I would like to get just Something as output
I tried:
<#list "${reasonValue}"?split("-") as sValue>
${sValue}
</#list>
but problem is that instead of real value i get name of ftl file...
Assign output of include to some variable and then use split on this variable.
<#assign xx>
<#include reasonValue>
</#assign>
<#list xx?split("-") as sValue>
${sValue}
</#list>
If you need to show only part of the string after "-" then use substring and index_of.
${xx?substring(xx?index_of("-") + 2)}
How to handle null values in Freemarker? I get some exceptions in the template when null values are present in data.
Starting from freemarker 2.3.7, you can use this syntax :
${(object.attribute)!}
or, if you want display a default text when the attribute is null :
${(object.attribute)!"default text"}
You can use the ?? test operator:
This checks if the attribute of the object is not null:
<#if object.attribute??></#if>
This checks if object or attribute is not null:
<#if (object.attribute)??></#if>
Source: FreeMarker Manual
I think it works the other way
<#if object.attribute??>
Do whatever you want....
</#if>
If object.attribute is NOT NULL, then the content will be printed.
Use ?? operator at the end of your <#if> statement.
This example demonstrates how to handle null values for two lists in a Freemaker template.
List of cars:
<#if cars??>
<#list cars as car>${car.owner};</#list>
</#if>
List of motocycles:
<#if motocycles??>
<#list motocycles as motocycle>${motocycle.owner};</#list>
</#if>
I would like to add more context if you have issues and this is what I have tried.
<#if Recipient.account_type?has_content>
… (executes if variable exists)
<#else>
… (executes if variable does not exist)
</#if>
This is more like Javascript IF and ELSE concept where we want to check whether this value or another chaining through required logic.
Freemarker webite
Other reference:
Scenario: Customer has ID and name combined like 13242 Harish, so where our stakeholder need the only name, so I have tried this ${record.entity?keep_after(" ")} and it did work, however, it can only work when you have space, but when a customer doesn't have space and one name, I had to do some IF ELSE condition to check Null value.
Use:
${(user.isSuperman!false)?c}
It will work when "isSuperman" is null and when have boolean value
What we want:
For "null" we want to output 'false'
For boolean value and want to output value ('true' or 'false')
What we know:
boolean need to convert to string by using "?c" see Built-ins for booleans
but null we cannot convert to string and we need to use "!" see Handling missing values