How to print any variable in FreeMarker? - freemarker

I have a Map<String, Object> which contains Strings, Doubles, Integers, Booleans and null (missing) as values. I want to print out the value in a FreeMarker template.
When I use ${data[field]!?html} it works for all other variables, but crashes on Boolean with:
freemarker.core._MiscTemplateException: Can't convert boolean to string automatically, because the "boolean_format" setting was "true,false", which is the legacy default computer-language format, and hence isn't accepted.
The application is an administration UI, where I don't that much care about the exact formatting, but I'd prefer booleans to use the standard true and false. (The boolean_format flag controls standard formatting of booleans, but using true and false seems to be explicitly prohibited for some mind-boggling reason.)
What's the best way to work around the FreeMarker prohibitation?

The way to achieve this is to use the ?string method: ${data[field]!?string?html}
This was mentioned only in the Configurable JavaDoc, and the ?string method is deprecated. I hope it's not going away anytime soone.

Starting from FreeMarker 2.3.29 you can set the boolean_format configuration setting to c, which will format booleans as ?c would, to true and false.

Related

Using tostring() to ensure functional conditionals in Terraform?

tl;dr: Is it an acceptable practice to use tostring() to cast values used for conditionals in Terraform >= 0.13 for handling a strictly defined set of input types?
Yesterday I asked a question that led me to a new question today:
Terraform count using bool?
What I learned is that there is some automatic type-casting applied to certain primitives in Terraform (going to and from strings to other data types mainly), but that these primitives cannot be used to infer a different data type (e.g. a bool cannot be passed as an input to the count argument because count only accepts a number type.
One comment on that question had a very simple way to use a bool as a condition:
count = var.my_var ? 1 : 0
The only potential issue with this, is if my_var can have different input types. In my use case, it'll be added to a Terraform module in which the user will decide what to supply for this argument; previously we've only been passing in string or number, but I find that to be a little less specific than I'd prefer, because Terraform can interpret count to be > 1 copy of a resource (I want a discrete 0 or 1 [specifically for something like var.create_this_resource whose value can be either true or false]); this also just doesn't look as nice to see "1" vs true IMO. So I'd like to start using bool instead, but also be able to handle when a user inputs a number. What I found is that I can use the following to accomplish this:
count = tostring(var.my_var) ? 1 : 0
Here, tostring() will take whatever is in the input and, presumably, cast it to a string. It only works for string, number, and boolean, and really, I'm only using it to get a number to a string because that's the only case where passing into a ternary operator is currently failing.
So my question is whether or not it's acceptable to do this? I've tested it with string, bool, and number, as well as unsupported types (i.e. an empty list or null); it seems to work well in code but the following made me think I shouldn't use it:
From the docs:
Explicit type conversions are rarely necessary in Terraform because it will convert types automatically where required. Use the explicit type conversion functions only to normalize types returned in module outputs.
In most cases I would suggest avoiding designs where a particular variable could have different types in different situations, unless your module is treating the value as entirely opaque and just passing it through to something else which has broader validation rules.
Since your module is working directly with this value, it would typically be best to specify an exact type constraint for the variable and make the caller of the module write expressions to convert the value if the automatic conversions are insufficient. That way the caller can get better feedback about what sort of value your module is expecting, and can decide for themselves how to convert their value of a different type.
Converting to string can only produce a value that can automatically convert to bool in the following situations:
The value was already a string, and was either "true" or "false".
The value was a bool value, in which case tostring will convert it to a string and then the conditional operator will immediately convert it back to bool again, which would be redundant.
If you declare the variable as being bool itself then the same rules will apply, but the conversion will happen inside the calling module block rather than in the count expression:
variable "my_var" {
type = bool
}
module "example" {
# ...
# This will automatically convert to bool true,
# just as it would've in the conditional operator.
my_var = "true"
}
If you really cannot avoid supporting various unusual ways of writing boolean values then you can potentially write your own conversion table which would be based on strings, and would specify the boolean value for each possible string after conversion:
locals {
sloppy_bool = tomap({
"1" = true
"true" = true
"0" = false
"false" = false
})
my_var = local.sloppy_bool[var.my_var]
}
Because mapping types (map types and object types) only support strings as keys, local.sloppy_bool[var.my_var] will automatically convert var.my_var to string, just as if you'd written tostring(var.my_var). It'll then look up the result in the table and return the corresponding boolean value, which means you can then use local.my_var instead of var.my_var elsewhere in your module and rely on it always being a true boolean value.
I would suggest doing this only if you had a previous version of the module which tolerated this sort of typing weirdness and you need to remain compatible with it. For an entirely new module, I would consider this to be non-idiomatic and probably confusing for anyone already familiar with Terraform who is trying to use the module, because they will need to become familiar with your unusual definition of the type conversion rather than relying on their knowledge of the built-in conversion rules.

Modelica: check equality of replaceable package or model

In my Modelica system model, I have a replaceable package (medium, fluid properties) and a replaceable model (pressure loss model). Can I somehow check whether a certain model or package is selected? The following approach does not work, but maybe explains what I want to achieve:
replaceable package Medium = Modelica.Media.Water.WaterIF97_ph;
Boolean isWater = (Medium == Modelica.Media.Water.WaterIF97_ph);
I was thinking of something similar like in python, were you can use type(variable) or isinstance(object, class). This approach seems to be doable in many languages, but is it possible in Modelica?
One workaround I thought of was to add some (or use an existing) constant inside the replaceable model/package and use that in the comparison, e.g. constant String mediumName or constant Integer correlationID, but I would see that as a workaround.
The workaround seems to work when using Integers, but not when using Strings. Any comment?
With comparison of constant Integer, I can calculate the correct value for the Boolean, but I hit another problem (in Dymola at least): When I use the Boolean in the annotation Dialog enable, it does not work. Is there a rule when the value of the Boolean gets evaluated?
The medium packages already have a property mediumName that you can compare, for instance using the code:
Boolean isWater = Modelica.Utilities.Strings.isEqual("WaterIF97", Medium.mediumName);
Best regards,
Rene Just Nielsen

Boolean parameters - should I name them?

so i just came across some code that reads like so:
checkCalculationPeriodFrequency("7D", "7D", SHOULD_MATCH);
and
checkCalculationPeriodFrequency("7D", "8D", SHOULD_NOT_MATCH);
Let's not worry about what the code does for now (or indeed, ever), but instead, let's worry about that last parameter - the SHOULD_MATCH and SHOULD_NOT_MATCH
Its something i've thought of before but thought might be "bad" to do (inasmuch as "bad" holds any real meaning in a postmodernist world).
above, those values are declared (as you might have assumed):
private boolean SHOULD_MATCH = true;
private boolean SHOULD_NOT_MATCH = false;
I can't recall reading about "naming" the boolean parameter passed to a method call to ease readability, but it certainly makes sense (for readability, but then, it also hides what the value is, if only a teeny bit). Is this a style thing that others have found is instagram or like, soooo facebook?
Naming the argument would help with readability, especially when the alternative is usually something like
checkCalculationFrequency("7D",
"8D",
true /* should match */);
which is ugly. Having context-specific constants could be a solution to this.
I would actually go a step further and redefine the function prototype to accept an enum instead:
enum MatchType {
ShouldMatch,
ShouldNotMatch
};
void checkCalculationFrequency(string a, string b, MatchType match);
I would prefer this over a boolean, because it gives you flexibility to extend the function to accept other MatchTypes later.
I suggest you not to do this way.
First, for each object, the two members SHOULD_MATCH and SHOULD_NOT_MATCH are regenerated. And that's not good because it's not a behavior of the object. So it you want to use is, at least describe it as STATIC FINAL.
Second, I prefer to use an enum instead, because you can control completely the value of the param, i.e. when you use it, you must use either SHOULD_MATCH or SHOULD_NOT_MATCH, not just true or false. And this increase the readability too.
Regards.
It is indeed for readability. The idea is that the reader of the function call might not know immediately what the value true mean in the function call, but SHOULD_MATCH conveys the meaning immediately (and if you need to look up the actual value, you can do so with not much effort).
This becomes even more understandable if you have more than one boolean parameters in the function call: which true means what?
The next step in this logic is to create named object values (e.g. via enum) for the parameter values: you cannot pass on the wrong value to the function (e.g. in the example of three boolean parameters, nothing stops me from passing in SHOULD_MATCH for all of them, even though it does not make sense semantically for that function).
It's definitely more than a style thing.
We have a similar system that takes takes input from a switch in the form of boolean values, 1 or 0, which is pretty much the same as true or false.
In this system we declare our variables OPEN = true and CLOSED = false* and pass them into functions which perform different actions depending on the state of the switch. Now if someone happens to hook up the switch differently it may be that we now get the value 0 when it is OPEN and 1 when it is CLOSED.
By having named boolean variables we can easily adapt the system without having to change the logic throughout. The code becomes self documenting because developers can clearer see what action is meant to be taken in which case without worrying what value comes.
Of course the true purpose of the boolean value should be well documented else where and it is in our system....honest....
*(maybe we use OPEN, !OPEN I forget)

Spring Expression Language (SpEL) with #Value: dollar vs. hash ($ vs. #)

I'm a little confused concerning when to use ${...} compared to #{...}. Spring's documentation only uses #{...}, but there are plenty of examples that use ${...}. Furthermore, when I started with SpEL I was told to use ${...} and it works fine.
For those who are confused, an example of how I use it would be
#Component
public class ProxyConfiguration {
#Value("${proxy.host}")
private String host;
#Value("${proxy.port}")
private String port;
:
}
and some property file:
proxy.host=myproxy.host
proxy.port=8000
My questions are:
what are the differences or is it the same?
is one version deprecated so I should use the other one?
${...} is the property placeholder syntax. It can only be used to dereference properties.
#{...} is SpEL syntax, which is far more capable and complex. It can also handle property placeholders, and a lot more besides.
Both are valid, and neither is deprecated.
${expr} --> Immediate Evaluation
#{expr} --> Deferred Evaluation
Immediate evaluation means that the expression is evaluated and the result returned as soon as the page is first rendered. Deferred evaluation means that the technology using the expression language can use its own machinery to evaluate the expression sometime later during the page’s lifecycle, whenever it is appropriate to do so.
Complete reference here
There is no JSP EL, JSP uses SpEL. SpEL fits to technology that is using it.
Try reading this article, which suggests
"If the hash is used, your code is recomputed every time that element is included in a partial refresh (i.e. each time it is rendered). If you use a dollar, your code is only computed when the page is initially loaded. But this has been extended beyond just EL, to SSJS too. After the hash or dollar, the curly braces denote the start and end of your language. This will be important when we come to combining languages later."
Expression Language Specification • Final Release - May 8, 2006
Page 2:
An eval-expression is formed by using the constructs ${expr} or #{expr}. Both
constructs are parsed and evaluated in exactly the same way by the EL, even though
they might carry different meanings in the technology that is using the EL.

test if string can be converted to a number in FreeMarker

I am trying to test whether a string can be converted into a number in FreeMarker. For example, "123" and "3.14" can be converted, but "foo" can't. I know that I can test for this by using the number method on the string (e.g. "123"?number) and seeing whether it produces an error, but I am looking for a way to test for this without causing an error.
I tried ?matches("^\d+$"), and it works fine for integers, but I am looking for something that works on all numbers.
I can probably do it using a more sophisticated regex, but I am wondering if there is a simpler way.
The simpler way is to not do it in FreeMarker :-) This sounds like something controller (or method on model) should be doing rather than view template. That said, you have a few options:
Use ?number built-in within <#attempt> / <#recover> block.
Write a method in one of your model objects to check whether your string into a number and invoke it from the template.
Write a custom directive to do this for you.

Resources