Nant nested if condition - nant

I am trying to do certain things when certain conditions are met, but it seems that somewhere my syntax is wrong. I need to have three if conditions to do one thing, but I'm not sure how to put in one of the if statements.
<if test="${build.MoniXXXtor == 'true'} or test="${build.XXX== 'true'}" or test="${build.yyy== 'true'}">
<property name="solutionFile" value="${svn.Lib.path}"/>
<property name="LocalPath" value="${Local.Lib.path}"/>
<call target="getLatest" if="${source.getLatest == 'true'}"/>
</if>
It seems the syntax for the OR condition above is wrong.

According to the documentation, you should use only one equals sign ( = instead of ==), e.g:
<if test="${build.configuration='release'}">
<echo>Build release configuration</echo>
</if>

Assuming that build.MoniXXXtor, build.XXX, and build.yyy are boolean properties the code is simply:
<if test="${build.MoniXXXtor or build.XXX or build.yyy}">
If they are string properties, they need to be converted to booleans:
<if test="${convert::to-boolean(build.MoniXXXtor) or
convert::to-boolean(build.XXX) or
convert::to-boolean(build.yyy)}">

Related

How can I use <bind> within a loop while using MyBatis?

I wanted to build a sql like "(column like 'a%' or column like 'b%' or ...)" and a,b,etc. are elements in a collection.
So I came up with xml file like this
<foreach item="item" collection="items" open="(" separator=" or " close=")">
<bind name="pattern" value="item + '%'" />
column like #{pattern}
</foreach
But it didn't work out as I thought it would be.
The sql was like "(column like 'c%' or column like 'c%' or ...)" which c is the last element in the collection.
Now I use a CONCAT function to do the job.
column like CONCAT(#{pattern},'%')
Is there other good ways to do the job?
Thanks.
It is a known limitation i.e. <bind /> cannot be used inside <foreach /> and there is an open issue.
Using CONCAT is a good workaround for now.

How to avoid getters when using mybatis dynamic sql?

In mybatis we can write an update statement like this:
<update id="update" parameterType="com.test.User">
update USERS
<set>
<if test="user.name != null">NAME=#{user.name},</if>
<if test="user.age != null">AGE=#{user.age}</if>
</set>
</update>
Then it requires User class to have getters for name and age properties, without the update statement, the mapping can work without adding any getters, is there a way to avoid the getters for the update statement?
It should work if you use the latest version 3.5.1 (the change was made in 3.5.0).
If you cannot upgrade for some reason, it may still work if you 1) remove the #Param("user") from the method parameter and 2) reference the fields directly as follows.
<update id="update">
update USERS
<set>
<if test="name != null">NAME=#{name},</if>
<if test="age != null">AGE=#{age}</if>
</set>
</update>
The direct property reference works only when the bean (i.e. User) is the only parameter to the mapper method.

How to calculate number of authors in EPrints (repository like DSpace)?

EPrints is a perl-based repository, see EPrints in WP
My librarian asked me to setup EPrins in the following way (only for the "monograph" type of documents):
If there are 3 or less authors then print 'authors' before title of the monograph;
If there more than 3 authors then print '$title / $authors'.
For example, 7 authors in first publication and 2 authors in second publication:
Analysis of the quotation corpus of the Russian Wiktionary / Smirnov A., Levashova T., Karpov A., Kipyatkova I., Ronzhin A., Krizhanovsky A., Krizhanovsky N. Research in Computing Science. 2012
Meyer C. M., Gurevych I. Worth its Weight in Gold or Yet Another Resource - A Comparative Study of Wiktionary, OpenThesaurus and GermaNet. 2010.
After several ours of try-and-fail attempts... The big problem is that EPrints is not pure Perl, and there are not too much documentation...
We need to edit the citations file /eprints/cfg/citations/eprint/default.xml). There is the following solution:
<!-- Monograph: if < 4 authors then print 'authors' before title -->
<when test="type = 'monograph'">
<if test="is_set(creators_name)">
<set name='authors' expr="creators_name">
(Debug information) Number of authors:
<print expr="$authors.length()"/>.
<set name='authors_len' expr="$authors.length()">
<if test="$authors_len lt 4">
<print expr="creators_name"/>
</if>
</set>
</set>
</if>
</when>
<!-- Title -->
<cite:linkhere><xhtml:em><print expr="title"/>:</xhtml:em></cite:linkhere>
<!-- "/ authors" after Title for monography if len(authors)>3 -->
<choose>
<when test="type = 'monograph'">
<if test="is_set(creators_name)">
<set name='authors' expr="creators_name">
<set name='authors_len' expr="$authors.length()">
<if test="$authors_len gt 3">
/ <print expr="creators_name"/>
</if>
</set>
</set>
</if>
</when>
<otherwise>
</otherwise>
</choose>
It works, but... I calculated twice the same variable "authors_len". And I don't know how to reuse this variable and calculate it only once.
I tried the EPrints function "is_set(authors_len)" and I tried "is_set($authors_len)", but EPrints throws different error messages o_O
I would use the following, checking for the creators_name being set, and how many creators there are:
<when test="type = 'monograph'">
<choose>
<when test="is_set(creators_name) and length(creators_name) lt 4">
<print expr="creators_name" />
/
<print expr="title" />
</when>
<when test="is_set(creators_name) and length(creators_name) gt 3">
<print expr="title" />
/
<print expr="creators_name" />
</when>
<otherwise>
<print expr="title" />
</otherwise>
</choose>
</when>
When using XML comments in an EPrints citation file, they will appear in the HTML source of the page. To make comments in the citation file that do not appear in the html source, you can use:
<comment>This will not appear in the html source</comment>
The language used for EPrints citations is documented on the EPrints Wiki:
https://wiki.eprints.org/w/EPScript
https://wiki.eprints.org/w/EPrints_Control_Format
Some XML configuration files use different default namespaces - so you may see the elements prefixed with a namespace e.g.
<cite:citation xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://eprints.org/ep3/control" xmlns:cite="http://eprints.org/ep3/citation" >
...
<epc:comment>This is a comment</epc:comment>
...
</cite:citation>
The best place for assistance with EPrints is their Mailing list - search the wiki (linked above) for details (I don't have enough reputation to post another link!).

How can I reuse an SQL fragment with parameters?

I'm intending to make a fragment for reusing with parameters.
<insert ...>
<selectKey keyProperty="id" resultType="_long" order="BEFORE">
<choose>
<when test="_databaseId == 'derby'">
VALUES NEXT VALUE FOR SOME_ID_SEQ
</when>
<otherwise>
SELECT SOME_ID_SEQ.NEXTVAL FROM DUAL
</otherwise>
</choose>
</selectKey>
INSERT INTO ...
</insert>
Can I make an SQL fragment using parameters?
<sql id="selectKeyFromSequence">
<selectKey keyProperty="id" resultType="_long" order="BEFORE">
<choose>
<when test="_databaseId == 'derby'">
VALUES NEXT VALUE FOR #{sequenceName}
</when>
<otherwise>
SELECT #{sequenceName}.NEXTVAL FROM DUAL
</otherwise>
</choose>
</selectKey>
</sql>
So that I can reuse them like this?
<insert ...>
<include refid="...selectKeyFromSequence"/> <!-- How can I pass a parameter? -->
INSERT INTO ...
</insert>
Is this possible?
As of version 3.3.0 you can do it like this:
<sql id="myinclude">
from ${myproperty}
</sql>
<include refid="myinclude">
<property name="myproperty" value="tablename"/>
</include>
See section SQL in http://www.mybatis.org/mybatis-3/sqlmap-xml.html
You cannot pass parameter to tags. There is a similar SO question, iBatis issue and a MyBatis issue.
Includes are in-lined when the xmls are parsed so the do not exist as
their own once the startup process finishes (from MyBatis issue).
However, you can use variables inside tags. You do not pass it as a parameter but you can give it as a parameter to the function that has the include tag. You need to use the same variable name in all functions, i.e. #{sequenceName}.

MyBatis iterate hashmap with foreach

I have a small problem with MyBatis. I'm trying to iterate over a Hashmap but it seems, that MyBatis is not able to do it. The name of the Hshmap is serviceMap. Here is the code of the MyBatis foreach:
<foreach item="item" index="key" collection="serviceMap" open="(" separator="or" close=")">
(upper(p.ENDPOINT) like upper(#{key})
and
upper(p.ENDPOINT_OPERATION) like upper(#item))
</foreach>
The exception is:
org.apache.ibatis.builder.BuilderException: Error evaluating expression 'serviceMap'. Return value ({vehicle=register}) was not iterable.
at org.apache.ibatis.builder.xml.dynamic.ExpressionEvaluator.evaluateIterable(ExpressionEvaluator.java:59)
at org.apache.ibatis.builder.xml.dynamic.ForEachSqlNode.apply(ForEachSqlNode.java:51)
at org.apache.ibatis.builder.xml.dynamic.MixedSqlNode.apply(MixedSqlNode.java:29)
at org.apache.ibatis.builder.xml.dynamic.IfSqlNode.apply(IfSqlNode.java:31)
at org.apache.ibatis.builder.xml.dynamic.MixedSqlNode.apply(MixedSqlNode.java:29)
Is MyBatis simply not able to do it or did I make an mistake?
It would be really nice, if anybody can help me.
Thanks a lot!
Stefan
A HashMap is not iterable. You need to iterate the entrySet.
<foreach item="item" index="key" collection="serviceMap.entrySet" open="(" separator="or" close=")">
(upper(p.ENDPOINT) like upper(#{key})
and
upper(p.ENDPOINT_OPERATION) like upper(#item))
<foreach item="item" index="key" collection="serviceMap.entrySet()" open="((" separator="),(" close="))">
(upper(p.ENDPOINT) like upper(#{item.key})
and
upper(p.ENDPOINT_OPERATION) like upper(#item.value))
</foreach>
Use the exact hashmap mechanism