I am converting velocity template to Freemarker and came across this condition below
=== Velocity Code ===
#if($frm_BenefitIcons.get("$beni.benefitIconNo"))
#set($xxx = $frm_BenefitIcons.get("$beni.benefitIconNo").toString().substring(12).toUpperCase())
#else
#set($xxx = "")
#end
and I converted it to freemarker as
=== Freemarker Code ===
<#if (frm_BenefitIcons.get("${(beni.benefitIconNo)!}"))??>
<#assign xxx = frm_BenefitIcons.get("${(beni.benefitIconNo)!}")?string?substring(12)?upper_case>
<#else>
<#assign xxx = "">
</#if>
is this correct conversion ? apart from using substring.
I am getting output only xxx = "" (which is else part of condition) but not actual value (if part of the condition). Velocity code gives output value for xxx.
In short (and assuming your Configuration uses the default ObjectWrapper, or similar), if the argument to get is a String, you should write frm_BenefitIcons[key]. If frm_BenefitIcons is a java.util.Map, you can't even call get. Unless, you explicitly tell that you want to call the Java API of the object: frm_BenefitIcons?api.get(key). This last is also how you could look up with a non-String key (as the [] operator doesn't support that).
As of the conversion, I think this will be cleaner:
<#assign benefitIcon = frm_BenefitIcons[beni.benefitIconNo?c]!>
<#assign xxx = (benefitIcon != '')?then(benefitIcon[12..]?upper_case, "")>
One critical part there is that where you convert a number (beni.benefitIconNo in this case) to a string, you must use ?c, not ?string, nor "${n}". Conversion to string without ?c is subject to localized formatting, like 1234 is possibly formatted to the string "1,234", which will break the lookup for you. ?c formats for Computer audience, as opposed to for human audience, and so avoids any cultural complication.
Related
I have text like this:
Forecaster Strongly disagree \n\nSomething else is going to happen\n\nExample:-\n\n#:hashtag/424 \n#:hashtag/2818 ",
I need to get 424 and 2818 (which are ids) and find titles for those ids and replace #:hashtag/424 with #Title1
How do I manipulate string for this?
You can use a regular expression like this:
RegExp exp = RegExp(r'#:hashtag\/(\d+)');
String test = "Forecaster Strongly disagree \n\nSomething else is going to happen\n\nExample:-\n\n#:hashtag/424 \n#:hashtag/2818";
final matches = exp.allMatches(test);
if(matches.isNotEmpty){
print (matches.first[0]!.split('/').last);
}
//prints 424
some additional null checks will probably be nececssary depending on what you can expect from the input string
To replace the IDs you could use the replaceAllMapped method like this:
test.replaceAllMapped(exp, (match) => match[0]!.split('/').first + '/#Title1');
I have one Contact us page with an intro blurb saying something like: Let us know how [we] can help you. The text inside the brackets needs to change based on the query string value.
For example:
If the URL is mysite.com/contact?p=product -> the text inside the
brackets is: [our technical sales rep]
If the URL is
mysite.com/contact?p=sf -> [our consultants in San Francisco office]
...
I can grab the query string value, but don't know how to use it with multiple ifs in the example above? Could you help?
For this your best bet is to create a custom macro method which will allow you to write a more robust logical statement and simply pass in the query string as the value.
The simplest approach is to pass along the actual string you want displayed in the URL as an encoded string and simply decode is when you get the value using a macro.
Your string text might look something like:
Let us know how {% QueryString.GetValue("p")|(default)"we" %} can help you.
Let us know how
{%
param = QueryString.p.ToLower().TrimEnd().TrimStart();
result = "we"; // default value
if(param == "product") {result ="our technical sales rep"}
if(param == "sf") {result = "our consultants in San Francisco office"}
if(param == "bla") {result = "bla bla bla"}
return result;
#%} can help you
I'm using the Apache POI framework for parsing large Excel spreadsheets. I'm using this example code as a guide: XLSX2CSV.java
I'm finding that cells that contain just numbers are implicitly being treated as numeric fields, while I wanted them to be treated always as strings. So rather than getting 1.00E+13 (which I'm currently getting) I'll get the original string value: 10020300000000.
The example code uses a XSSFSheetXMLHandler which is passed an instance of DataFormatter. Is there a way to use that DataFormatter to treat all cells as strings?
Or as an alternative: in the implementation of the interface SheetContentsHandler.cell method there is string value that is the cellReference. Is there a way to convert a cellReference into an index so that I can use the SharedStringsTable.getEntryAt(int idx) method to read directly from the strings table?
To reproduce the issue, just run the sample code on an xlsx file of your choice with a number like the one in my example above.
UPDATE: It turns out that the string value I get seems to match what you would see in Excel. So I guess that's going to be "good enough" generally. I'd expect the data I'm sent to "look right" and therefore it'll get parsed correctly. However, I'm sure there will be mistakes and in those cases it'd be nice if I could get at the raw string value using the streaming API.
To resolve this issue I created my own class based on XSSFSheetXMLHandler
I copied that class, renamed it and then in the endElement method I changed this part of the code which is formatting the raw string:
case NUMBER:
String n = value.toString();
if (this.formatString != null && n.length() > 0)
thisStr = formatter.formatRawCellContents(Double.parseDouble(n), this.formatIndex, this.formatString);
else
thisStr = n;
break;
I changed it so that it would not format the raw string:
case NUMBER:
thisStr = value.toString();
break;
Now every number in my spreadsheet has its raw value returned rather than a formatted version.
I am trying to check if a key of a map in freemarker matches a particular string. How can I do that?
<#if (list_map.id)!?matches(("abc"))>
you matched ...
</#if>
but the above doesn't work in freemarker. It says matches expects a string. How can I convert list_map.id to a string ? is there any toString() method available in freemarkeR?
If id is a number, then probably you want list_map.id?c to render it to computer-format string.
I currently have an Event Receiver that is attached to a custom list. My current requirement is to implement column level security for a Rich Text field (Multiple lines of text with enhanced rich text).
According to this post[webarchive], I can get the field's before and after values like so:
object oBefore = properties.ListItem[f.InternalName];
object oAfter = properties.AfterProperties[f.InternalName];
The problem is that I'm running to issues comparing these two values, which lead to false positives (code is detecting a change when there wasn't one).
Exhibit A: Using ToString on both objects
oBefore.ToString()
<div class=ExternalClass271E860C95FF42C6902BE21043F01572>
<p class=MsoNormal style="margin:0in 0in 0pt">Text.
</div>
oAfter.ToString()
<DIV class=ExternalClass271E860C95FF42C6902BE21043F01572>
<P class=MsoNormal style="MARGIN: 0in 0in 0pt">Text.
</DIV>
Problems?
HTML tags are capitalized
Random spaces (see the additional space after margin:)
Using GetFieldValueForEdit or GetFieldValueAsHTML seem to result in the same values.
"OK," you say, so lets just compare the plain text values.
Exhibit B: Using GetFieldValueAsText
Fortunately, this method strips all of the HTML tags out of the value and only plain text is displayed. However, using this method led me to discover additional issues with whitespace characters:
In the before value:
Sometimes there are additional newline characters.
Sometimes spaces are displayed as non-breaking spaces (ASCII char code 160)
Question:
How can I detect if the user changed a rich text field in an event receiver?
[Ideal] Detect any change to HTML or text or white space
[Acceptable] Detect changes to text or white space
[Not so good] Detect changes to text characters only (strip all non-alphanumeric characters)
What happens if you set the ListItem field with the new value and read it back out? Does that give the same formatting?
object oBefore = properties.ListItem[f.InternalName];
properties.ListItem[f.InternalName] = properties.AfterProperties[f.InternalName]
object oAfter = properties.ListItem[f.InternalName];
//dont update
properties.ListItem[f.InternalName] = oBefore;
I would probably try something between choices 2 and 3:
bool changed =
valueAsTextBefore != valueAsTextAfter ||
0 != string.Compare(
oBefore.ToString().Replace(" ", ""),
oAfter.ToString().Replace(" ", ""),
true);
The left half checks if the text (including case) has changed while the right half checks if the tags or attributes have changed. Very kludgy, but should fit your case.
The only other thing I can think of is to run an XML transform on the HTML in order to standardize on case and spacing. But not only does that seem like overkill, but it assumes the HTML will always be well formed.
I'm currently testing a combination approach: GetFieldValueAsText and then stripping out all characters except alphanumeric/punctuation:
static string GetRichTextValue(string value)
{
if (null == value)
{
return string.Empty;
}
StringBuilder sb = new StringBuilder(value.Length);
foreach (char c in value)
{
if (char.IsLetterOrDigit(c) || char.IsPunctuation(c))
{
sb.Append(c);
}
}
return sb.ToString();
}
This only detects changes to the text of a rich text field but seems to work consistently.