Subtraction in ant - ant

I have two properties in Ant that both contain integers. I want to check if one is greater than the other. How can I accomplish that? Is there a way to use subtraction in ant? Then I could just subtract the two and check if the result is greater than 0.
Thanks!

You can try to use this sample:
<scriptdef name="intCompare" language="javascript">
<attribute name="leftside"/>
<attribute name="rightside"/>
<attribute name="diff"/>
<![CDATA[
var leftSide = attributes.get("leftside");
var rightSide = attributes.get("rightside");
project.setProperty(attributes.get("diff"), leftSide-rightSide);
]]>
</scriptdef>
<target name="test">
<intCompare leftside="555" rightside="9" diff="deviation"/>
<echo message="The difference is: ${deviation}"/>
</target>

Use a groovy task
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
properties["greater"] = properties["x"] > properties["y"]
</groovy>

Related

Ant substring by position

I need to extract a substring from property value by length, f.e. :
<property name="prop1" value="nameBLABLABLA" />
I want get the value
name
Is it possible without using javascript code ?
Not with vanilla ant, you would need to add some Ant addon like Antcontrib (latest release 2006 !) or Ant Flaka - means you'll need additional jars/libraries.
With using the jdk builtin Javascript engine it's as easy as :
<project>
<!-- create a macrodef for reuse -->
<macrodef name="getsubstring">
<attribute name="src"/>
<attribute name="from"/>
<attribute name="to"/>
<attribute name="result"/>
<sequential>
<script language="javascript">
project.setProperty(
"#{result}", "#{src}".substring(#{from},#{to})
);
</script>
</sequential>
</macrodef>
<property name="foo" value="nameBLABLABLA"/>
<getsubstring src="${foo}" from="0" to="4" result="foobar"/>
<echo> $${foobar} => ${foobar}</echo>
</project>
No additional libraries needed.
Created a macrodef that works for properties respectively for strings in general.
The JavaScript engine understands Javascript and Java and you'll get full access to Ant api.
I'd use JavaScript as in Rebse's answer, but there is a way to do this without it using <loadresource> and a <tokenfilter>. This uses start/length rather than from/to for the substring:
<macrodef name="getsubstring">
<attribute name="src"/>
<attribute name="start"/>
<attribute name="length"/>
<attribute name="result"/>
<sequential>
<loadresource property="#{result}">
<string value="#{src}}" />
<filterchain>
<tokenfilter>
<replaceregex pattern="^.{#{start}}(.{#{length}}).*" replace="\1" />
</tokenfilter>
</filterchain>
</loadresource>
</sequential>
</macrodef>
<property name="prop1" value="nameBLABLABLA" />
<getsubstring src="${prop1}" start="0" length="4" result="p"/>
<echo message="${p}" />

Ant - String contains within an array of String

I am basically trying to do the following thing in Ant (v1.9.4):
I have a list of fixed string like {a,b,c,d} --> First how should I declare this in Ant?
Then I have an input parameter such as ${mystring} and I want to check if the variable value is in my list. Which means in this example, if the variable value is equals to a or b or c or d.
If so return true else false (or 0 and 1 something like that).
Is there a simple way to do that?
Thanks,
Thiago
Use ant property task to declare your stringlist.
Use ant contains condition to check whether list contains a specific item.
Something like :
<project>
<!-- your stringlist -->
<property name="csvprop" value="foo,bar,foobar"/>
<!-- fail if 'foobaz' is missing -->
<fail message="foobaz not in List => [${csvprop}]">
<condition>
<not>
<contains string="${csvprop}" substring="foobaz"/>
</not>
</condition>
</fail>
</project>
Or wrap it in a macrodef for resuse :
<project>
<!-- your stringlist -->
<property name="csvprop" value="foo,bar,foobar"/>
<!-- create macrodef -->
<macrodef name="listcontains">
<attribute name="list"/>
<attribute name="item"/>
<sequential>
<fail message="#{item} not in List => [#{list}]">
<condition>
<not>
<contains string="${csvprop}" substring="foobaz"/>
</not>
</condition>
</fail>
</sequential>
</macrodef>
<!-- use macrodef -->
<listcontains item="foobaz" list="${csvprop}"/>
</project>
-- EDIT --
From ant manual condition :
If the condition holds true, the property value is set to true by default; otherwise, the property is not set. You can set the value to something other than the default by specifying the value attribute.
So simply use a condition to create a property that is either true or not set, f.e. combined with the new if/unless feature introduced with Ant 1.9.1 :
<project
xmlns:if="ant:if"
xmlns:unless="ant:unless"
>
<!-- your stringlist -->
<property name="csvprop" value="foo,bar,foobar"/>
<!-- create macrodef -->
<macrodef name="listcontains">
<attribute name="list"/>
<attribute name="item"/>
<sequential>
<condition property="itemfound">
<contains string="${csvprop}" substring="foobaz"/>
</condition>
<!-- echo as example only instead of
your real stuff -->
<echo if:true="${itemfound}">Item #{item} found => OK !!</echo>
<echo unless:true="${itemfound}">Warning => Item #{item} not found !!</echo>
</sequential>
</macrodef>
<!-- use macrodef -->
<listcontains item="foobaz" list="${csvprop}"/>
</project>
output :
[echo] Warning => Item foobaz not found !!
Note that you need the namespace declarations to activate the if/unless feature.

Macrodef in Ant : passing a value outside the definition

I have the following macro definition in Ant and I would like to pass the "cmdStatus" value outside this macro def:
<macrodef name="execEtlBinScript">
<attribute name="script" />
<sequential>
<exec executable="#{script}" resultproperty="cmdStatus"/>
</sequential>
</macrodef>
Do you have any idea if it is possible or not ?
Thank you for any help.
Kind regards,
foxrafi
In your exemple, the property cmdStatus is set and is then available outside the macrodef. But I guess that your issue is that if your call several times your macro, you don't get the next status values as properties in Ant are immutable.
The way to handle it properly is to make the result property an attribute of the macro:
<macrodef name="execEtlBinScript">
<attribute name="script" />
<attribute name="resultproperty" />
<sequential>
<exec executable="#{script}" resultproperty="#{resultproperty}"/>
</sequential>
</macrodef>
Then each call to the macrodef will get its value via a different property:
<execEtlBinScript script="somescript" resultproperty="status1" />
<echo message="Result of the first call: ${status1}" />
<execEtlBinScript script="somescript" resultproperty="status2" />
<echo message="Result of the second call: ${status2}" />

Macrodef and "local properties"

I am trying to move a file (specified by a pattern) to a given location in an Ant macrodef:
<macrodef name="extract">
<attribute name="package"/>
<sequential>
<!-- the path will contain the unique file in extracted regardless of the name -->
<path id="source_refid">
<dirset dir="${dep}/lib/#{package}/extracted/">
<include name="#{package}-*"/>
</dirset>
</path>
<!-- this is not working: properties are immutable -->
<property name="source_name" refid="source_refid"/>
<move
file="${source_name}"
tofile="${dep}/#{package}/"
overwrite="true"
/>
</sequential>
</macrodef>
This will work just once as ${source_name} is immutable.
An option would be to use the variable task but I didn't find a way to assign a refid to a var.
Is there a way to have something similar to local variable in a macrodef? Or (XY problem) is there a better way to solve my problem?
Since Ant 1.8 you can use the local task for this. For example:
<local name="source_name"/>
<property name="source_name" refid="source_refid"/>
Your example is just the sort of thing local is for!

How can I compare two properties with numeric values?

How can I find out which of two numeric properties is the greatest?
Here's how to check wheather two are equal:
<condition property="isEqual">
<equals arg1="1" arg2="2"/>
</condition>
The Ant script task allows you to implement a task in a scripting language. If you have JDK 1.6 installed, Ant can execute JavaScript without needing any additional dependent libraries. For example, this JavaScript reads an Ant property value and then sets another Ant property depending on a condition:
<property name="version" value="2"/>
<target name="init">
<script language="javascript"><![CDATA[
var version = parseInt(project.getProperty('version'));
project.setProperty('isGreater', version > 1);
]]></script>
<echo message="${isGreater}"/>
</target>
Unfortunately, Ant's built in condition task does not have an IsGreaterThan element. However, you could use the IsGreaterThan condition available in the Ant-Contrib project. Another option would be to roll out your own task for greater than comparison. I'd prefer the former, because it's easier and faster, and you also get a host of other useful tasks from Ant-Contrib.
If you don't want to (or cannot) use the Ant-Contrib libraries, you can define a compare task using javascript:
<!-- returns the same results as Java's compareTo() method: -->
<!-- -1 if arg1 < arg2, 0 if arg1 = arg2, 1 if arg1 > arg2 -->
<scriptdef language="javascript" name="compare">
<attribute name="arg1" />
<attribute name="arg2" />
<attribute name="result" />
<![CDATA[
var val1 = parseInt(attributes.get("arg1"));
var val2 = parseInt(attributes.get("arg2"));
var result = (val1 > val2 ? 1 : (val1 < val2 ? -1 : 0));
project.setProperty(attributes.get("result"), result);
]]>
</scriptdef>
You can use it like this:
<property name="myproperty" value="20" />
...
<local name="compareResult" />
<compare arg1="${myproperty}" arg2="19" result="compareResult" />
<fail message="myproperty (${myproperty}) is greater than 19!">
<condition>
<equals arg1="${compareResult}" arg2="1" />
</condition>
</fail>

Resources