Came across the follow line in a freemarker document for checking if there are more elements:
<#list myList as myVar>...<#if myVar_has_next>...</#if></#list>
I know about the "?" for calling built-ins, and about "has_next", i.e. myVar?has_next. What I am not familiar with using an underscore between the var and the built-in. Is this a legacy syntax?
It seems that this is an undocumented a feature. The relevant code in freemarker.core.IteratorBlock shows that myVar_has_next is really just the name of a variable. But because the code checks for occurences of _has_next (and _index, fwiw) appended to the loop variable name (myVar), Freemarker is able to put a value to this variable.
At least with Freemarker 2.3.23, I cannot reproduce the error that you mentioned. The following code works just fine although it uses myVar?has_next
public static void main(String[] args) throws IOException, TemplateException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_23);
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
Template template = new Template("test", "<#list myList as myVar>${myVar} <#if myVar?has_next>has next. </#if></#list>", cfg);
template.process((Object) Collections.singletonMap("myList", Arrays.asList("a", "b", "c")), new OutputStreamWriter(System.out));
}
Produces
a has next. b has next. c
Edit: This feature has been deprecated in v2.3.23 (see #ddekany's comment)
Related
I have following Extension Method which is just a negation of Linq.Any()
These two UnitTests do test it completely
[TestMethod]
public void EnumerableExtensions_None_WithMatch()
{
Assert.IsTrue(_animals.None(t => t.Name == "Pony"));
}
[TestMethod]
public void EnumerableExtensions_None()
{
var emtpyList = new List<Animal>(); { };
Assert.IsTrue(emtpyList.None());
}
As you can see in the picture, when I run a Code Coverage Analysis, the delegate body is not covered (white selection), because of the deferred execution.
This question comes close to the problem:
Code Coverage on Lambda Expressions
But does not quite solve it: Since the List must stay empty, it's impossible to actually step into that piece of code.
I am tempted to mark the segment with [ExcludeFromCodeCoverage] ...
How would you write the UnitTest?
You need to test that None() returns false when given a non-empty list of Animal. As it is, you never execute your default lambda expression.
You might even find a bug...
This is the correct way to write the Test. Even found a bug!
public void EnumerableExtensions_None()
{
// _animals HAS entries
Assert.IsFalse(_animals.None());
}
Code Coverage 100%!
Today I was faced with the prospect of writing quite a few freemarker expressions. While the overall difficulty is not high, some of them will contain quite a few builtin calls (i.e. parsing formatted string to number, increasing it and formatting again).
That got me to thinking - how can I test that for development purpuses only to minimize the time spent? I know there are IDE tools that help with the syntax - however, what about testing the functionality I wrote on sample strings? Something that would allow me to parse ${" b lah"?trim} and check whether the output is what I expect? Running my app is obviously a possibility, but in my case it takes way too long to get to the part where using freemarker happens.
I would use a simple JUnit test to test that.
Example:
public class FreemarkerSandbox {
#Test
public void testFreemarker() throws TemplateException, IOException {
Configuration cfg = new Configuration();
Template template = cfg.getTemplate("trim.ftl", CharEncoding.UTF_8);
HashMap<String, Object> model = new HashMap<String, Object>();
Writer out = new StringWriter();
template.process(model, out);
assertEquals("b lah", out.toString());
}
}
With trim.ftl just containing the expression to test.
${" b lah"?trim}
It can be improved by passing the test cases in the model.
I'm creating a file that isn't really a csv file, but SuperCSV can help me to make the creation of this file easier. The structure of the file uses different lengths for each line, following a layout that don't separate the different information. So, to know which information has in one line you need look at the first 2 characters (the name of the register), count the characters and extract it by size.
I've configured SuperCSV to use empty delimiter, however, the created file is using a space where it should have nothing.
public class TarefaGerarArquivoRegistrosFiscais implements ITarefa {
private static final CsvPreference FORMATO_ANEXO_IV = new CsvPreference.Builder('"', '\0' , "\r\n").build();
public void processar() {
try {
writer = new CsvListWriter(getFileWriter(), FORMATO_ANEXO_IV);
writer.write(geradorRegistroU1.gerar());
} finally {
if (writer != null)
writer.close();
}
}
}
I'm doing something wrong? '\0' is the correct code for a null char?
It's probably not what you want to hear, but I wouldn't recommend using Super CSV for this (and I'm a committer!). Its sole purpose is to deal with delimited files - and you're not using delimiters.
You could misuse Super CSV by creating a wrapper object (containing your List) whose toString() method simply concatenates all of the values together, then passing that single object to writer.write(), but it's an awful hack.
I'd recommend either finding another library more suited to your problem, or writing your own solution.
I've been using JoSQL for quite a few months now and today I came across a problem I am not sure how to solve. I probably could solve it by binding variables/placeholders, but I'd like to include the fields in the query.
SELECT * FROM ...MyObject WHERE getType != com.mypackage.myclass.TYPE_A
This is the query that I have. TYPE_A is a public static final int attribute in "myclass" class. Accessing methods (such as getType) is easy, because getType is expected to be a method from MyObject - just that I do not write round brackets after it (this is how JoSQL works as far as I know).
Does anyone happen to have an idea how to access a public static final field?
JoSQL uses gentlyweb-utils; it seems to be some sort of Accessor/Getter/Setter framework. I'd love to access that attribute without having to bind variables, but I haven't been able to do so.
Thanks for your help in advance! I really appreciate it.
I think I have figured something out. First: it seems not possible to access the static variables for whatever reason. I've used the following approach to solve my issue:
create a method, which picks up a given JoSQL-statement
mark the constants, which you want to replace, by say "{?FULL_PACKAGE_AND$CONSTANT}"
use reflections to determine the column as well as the column (and value) from the field
iteratively replace the statement until no "{?"-values are available
Example:
JoSQL-statement looks like this:
(isWeapon = TRUE AND getItem.getType2 = {?com.l2jserver.gameserver.model.items.L2Item$TYPE2_WEAPON})
Method using the query-object:
final Query query = DataLayer.createJoSqlQuery(joSql);
Method (pre)processing the JoSQL-statement:
final Query query = new Query();
int variableColumn = 0;
while (joSql.indexOf("{?") > -1) {
variableColumn++;
final int startIndex = joSql.indexOf("{?");
final int endIndex = joSql.indexOf("}", startIndex);
final String value = joSql.substring(startIndex + 2, endIndex);
try {
final Object variableValue = Class.forName(value.split("\\$")[0]).getField(value.split("\\$")[1]).get(null);
query.setVariable(variableColumn, variableValue);
joSql = joSql.replace("{?" + value + "}", "?");
}
catch (...) {
e.printStackTrace();
}
}
query.parse(joSql);
return query;
The JoSQL-statement preprocessing method bascially iterates through a given JoSQL-statement and sees whether it contains the string "{?". If it does, it does some copy and paste (note the dollar-symbol right in front of the constant name).
Finally it creates the objects and sets them using something similar to prepared statements "setObject"-method. In the end it just replaces the values within the JoSQL-statement with question marks ("?") and sets a corresponding object in the newly created Query-object, which is later used to retrieve information.
Why is LINQ allowed to have spaces in the statement? An example statement:
var questions = from item in db.questions
select item;
As a programmer, we cannot create functions or methods with spaces in them, or anything that resembles the LINQ syntax. Is this something that is just specially parsed by the language? Would there be any way to let programmers make up their own LINQ-like statements?
Because they are "keywords" (technically they are "contextual keywords". They are "keywords" only in certain places) :-) Look here: Query Keywords (C# Reference) and C# Keywords
Why can you write public static void with spaces? Because they are keywords :-)
And no, you can't add new keywords to C#.
(but note that you can use the LINQ syntax on non-IEnumerable/IQueryable objects. LINQ syntax is converted "blindly" to specific method names. The compiler doesn't check if they are really IEnumerable<T> or IQueryable<T>)
Try this:
class Test
{
public Test Where(Func<Test, bool> predicate)
{
Console.WriteLine("Doing the Where");
return this;
}
public T Select<T>(Func<Test, T> action)
{
Console.WriteLine("Doing the Select");
return action(this);
}
}
var res = from p in new Test() where p != null select new Test();
It's syntactic sugar that the compiler understands. You can't change the compiler so can't do the same I'm afraid