git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@808009 13f79535-47bb-0310-9956-ffa450edef68master
@@ -73,6 +73,7 @@ David Gärtner | |||||
David S. Johnson | David S. Johnson | ||||
David Kavanagh | David Kavanagh | ||||
David LeRoy | David LeRoy | ||||
David Leal | |||||
David M. Lloyd | David M. Lloyd | ||||
David Maclean | David Maclean | ||||
David Rees | David Rees | ||||
@@ -923,6 +923,10 @@ Other changes: | |||||
parent directory of the destination archive if it doesn't exist. | parent directory of the destination archive if it doesn't exist. | ||||
Bugzilla Report 45377. | Bugzilla Report 45377. | ||||
* A new filterreader <sortfilter> that sorts input lines has been | |||||
added. | |||||
Bugzilla Report 40504. | |||||
Changes from Ant 1.7.0 TO Ant 1.7.1 | Changes from Ant 1.7.0 TO Ant 1.7.1 | ||||
============================================= | ============================================= | ||||
@@ -316,6 +316,10 @@ | |||||
<first>David</first> | <first>David</first> | ||||
<last>LeRoy</last> | <last>LeRoy</last> | ||||
</name> | </name> | ||||
<name> | |||||
<first>David</first> | |||||
<last>Leal</last> | |||||
</name> | |||||
<name> | <name> | ||||
<first>David</first> | <first>David</first> | ||||
<middle>M.</middle> | <middle>M.</middle> | ||||
@@ -124,6 +124,7 @@ nested elements.<br> | |||||
<a href="#concatfilter">ConcatFilter</a><br> | <a href="#concatfilter">ConcatFilter</a><br> | ||||
<a href="#tokenfilter">TokenFilter</a><br> | <a href="#tokenfilter">TokenFilter</a><br> | ||||
<a href="../CoreTasks/fixcrlf.html">FixCRLF</a><br> | <a href="../CoreTasks/fixcrlf.html">FixCRLF</a><br> | ||||
<a href="#sortfilter">SortFilter</a><br> | |||||
<h3><a name="filterreader">FilterReader</a></h3> | <h3><a name="filterreader">FilterReader</a></h3> | ||||
@@ -1481,7 +1482,7 @@ public class Capitalize | |||||
This may be used as follows: | This may be used as follows: | ||||
<blockquote><pre> | <blockquote><pre> | ||||
<typedef type="capitalize" classname="my.customant.Capitalize" | |||||
<typedef name="capitalize" classname="my.customant.Capitalize" | |||||
classpath="my.customant.path"/> | classpath="my.customant.path"/> | ||||
<copy file="input" tofile="output"> | <copy file="input" tofile="output"> | ||||
<filterchain> | <filterchain> | ||||
@@ -1493,4 +1494,97 @@ This may be used as follows: | |||||
</copy> | </copy> | ||||
</pre></blockquote> | </pre></blockquote> | ||||
<h3><a name="sortfilter">SortFilter</a></h3> | |||||
<p>This filter sorts lines lexicographically but you can specifiy a | |||||
custom comparator as well.</p> | |||||
<table cellSpacing=0 cellPadding=2 border=1> | |||||
<tr> | |||||
<td vAlign=top><b>Parameter Type</b></td> | |||||
<td vAlign=top><b>Parameter Value</b></td> | |||||
<td vAlign=top align="center"><b>Required</b></td> | |||||
</tr> | |||||
<tr> | |||||
<td vAlign=top>reverse</td> | |||||
<td vAlign=top align="center">Whether to reverse the sort order | |||||
(boolean). Will be ignored if a custom comparator has been | |||||
specified.</td> | |||||
<td vAlign=top align="center">No</td> | |||||
</tr> | |||||
<tr> | |||||
<td vAlign=top>comparator</td> | |||||
<td vAlign=top align="center">Classname of a class | |||||
implementing <code>java.util.Comparator</code> an instance of | |||||
which will be used when comparing lines.</td> | |||||
<td vAlign=top align="center">No</td> | |||||
</tr> | |||||
</table> | |||||
<p> | |||||
<h4>Example:</h4> | |||||
This will sort the lines. | |||||
<blockquote><pre> | |||||
<filterreader classname="org.apache.tools.ant.filters.SortFilter"/> | |||||
</pre></blockquote> | |||||
Convenience method: | |||||
<blockquote><pre> | |||||
<sortfilter/> | |||||
</pre></blockquote> | |||||
This will reverse the sort order. | |||||
<blockquote><pre> | |||||
<filterreader classname="org.apache.tools.ant.filters.SortFilter"> | |||||
<param name="reverse" value="true"/> | |||||
</filterreader> | |||||
</pre></blockquote> | |||||
Convenience method: | |||||
<blockquote><pre> | |||||
<sortfilter reverse="true"/> | |||||
</pre></blockquote> | |||||
You can use your own comparator, the easiest way is by using typedef | |||||
and the convenience method which allows to specify the comparator as a | |||||
nested element: | |||||
<blockquote><pre> | |||||
public final class EvenFirstCmp implements Comparator { | |||||
public int compare(Object o1, Object o2) { | |||||
String s1 = ((String) o1).substring(5).trim(); | |||||
String s2 = ((String) o2).substring(5).trim(); | |||||
int n1 = Integer.parseInt(s1); | |||||
int n2 = Integer.parseInt(s2); | |||||
if (n1 % 2 == 0) { | |||||
if (n2 % 2 == 0) { | |||||
return n1 - n2; | |||||
} else { | |||||
return -1; | |||||
} | |||||
} else { | |||||
if (n2 % 2 == 0) { | |||||
return 1; | |||||
} else { | |||||
return n1 - n2; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
</pre></blockquote> | |||||
and used as | |||||
<blockquote><pre> | |||||
<typedef classname="org.apache.tools.ant.filters.EvenFirstCmp" | |||||
name="evenfirst"/> | |||||
... | |||||
<filterchain> | |||||
<sortfilter> | |||||
<evenfirst/> | |||||
</sortfilter> | |||||
</filterchain> | |||||
</pre></blockquote> | |||||
</body></html> | </body></html> |
@@ -51,6 +51,8 @@ | |||||
classname="org.apache.tools.ant.taskdefs.condition.IsFailure"/> | classname="org.apache.tools.ant.taskdefs.condition.IsFailure"/> | ||||
<componentdef name="isfalse" onerror="ignore" | <componentdef name="isfalse" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.IsFalse"/> | classname="org.apache.tools.ant.taskdefs.condition.IsFalse"/> | ||||
<componentdef name="islastmodified" onerror="ignore" | |||||
classname="org.apache.tools.ant.taskdefs.condition.IsLastModified"/> | |||||
<componentdef name="isreachable" onerror="ignore" | <componentdef name="isreachable" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.IsReachable"/> | classname="org.apache.tools.ant.taskdefs.condition.IsReachable"/> | ||||
<componentdef name="isreference" onerror="ignore" | <componentdef name="isreference" onerror="ignore" | ||||
@@ -73,6 +75,8 @@ | |||||
classname="org.apache.tools.ant.taskdefs.condition.ParserSupports"/> | classname="org.apache.tools.ant.taskdefs.condition.ParserSupports"/> | ||||
<componentdef name="resourcecontains" onerror="ignore" | <componentdef name="resourcecontains" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.ResourceContains"/> | classname="org.apache.tools.ant.taskdefs.condition.ResourceContains"/> | ||||
<componentdef name="resourceexists" onerror="ignore" | |||||
classname="org.apache.tools.ant.taskdefs.condition.ResourceExists"/> | |||||
<componentdef name="resourcesmatch" onerror="ignore" | <componentdef name="resourcesmatch" onerror="ignore" | ||||
classname="org.apache.tools.ant.taskdefs.condition.ResourcesMatch"/> | classname="org.apache.tools.ant.taskdefs.condition.ResourcesMatch"/> | ||||
<componentdef name="socket" onerror="ignore" | <componentdef name="socket" onerror="ignore" | ||||
@@ -131,5 +135,8 @@ | |||||
<componentdef name="reverse" onerror="ignore" | <componentdef name="reverse" onerror="ignore" | ||||
classname="org.apache.tools.ant.types.resources.comparators.Reverse" /> | classname="org.apache.tools.ant.types.resources.comparators.Reverse" /> | ||||
<!-- filters --> | |||||
<componentdef name="sortfilter" onerror="ignore" | |||||
classname="org.apache.tools.ant.filters.SortFilter"/> | |||||
</antlib> | </antlib> | ||||
@@ -0,0 +1,362 @@ | |||||
/* | |||||
* Licensed to the Apache Software Foundation (ASF) under one or more | |||||
* contributor license agreements. See the NOTICE file distributed with | |||||
* this work for additional information regarding copyright ownership. | |||||
* The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
* (the "License"); you may not use this file except in compliance with | |||||
* the License. You may obtain a copy of the License at | |||||
* | |||||
* http://www.apache.org/licenses/LICENSE-2.0 | |||||
* | |||||
* Unless required by applicable law or agreed to in writing, software | |||||
* distributed under the License is distributed on an "AS IS" BASIS, | |||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
* See the License for the specific language governing permissions and | |||||
* limitations under the License. | |||||
* | |||||
*/ | |||||
package org.apache.tools.ant.filters; | |||||
import java.io.IOException; | |||||
import java.io.Reader; | |||||
import java.util.ArrayList; | |||||
import java.util.Collections; | |||||
import java.util.Comparator; | |||||
import java.util.Iterator; | |||||
import java.util.List; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.Parameter; | |||||
/** | |||||
* <p> | |||||
* Sort a file before and/or after the file. | |||||
* </p> | |||||
* | |||||
* <p> | |||||
* Examples: | |||||
* </p> | |||||
* | |||||
* <pre> | |||||
* <copy todir="build"> | |||||
* <fileset dir="input" includes="*.txt"/> | |||||
* <filterchain> | |||||
* <sortfilter/> | |||||
* </filterchain> | |||||
* </copy> | |||||
* </pre> | |||||
* | |||||
* <p> | |||||
* Sort all files <code>*.txt</code> from <i>src</i> location in descendant | |||||
* order and copy them into <i>build</i> location. The lines of each file are | |||||
* sorted in ascendant order comparing the lines vía | |||||
* <code>String.compareTo(Object o)</code> method. | |||||
* </p> | |||||
* | |||||
* <pre> | |||||
* <copy todir="build"> | |||||
* <fileset dir="input" includes="*.txt"/> | |||||
* <filterchain> | |||||
* <sortfilter/> | |||||
* <param name="reverse" value="true"/> | |||||
* </sortfilter/> | |||||
* </filterchain> | |||||
* </copy> | |||||
* </pre> | |||||
* | |||||
* <p> | |||||
* Sort all files <code>*.txt</code> from <i>src</i> location into reverse | |||||
* order and copy them into <i>build</i> location. If reverse parameter has | |||||
* value <code>true</code> (default value), then the output line of the files | |||||
* will be in ascendant order. | |||||
* </p> | |||||
* | |||||
* <pre> | |||||
* <copy todir="build"> | |||||
* <fileset dir="input" includes="*.txt"/> | |||||
* <filterchain> | |||||
* <sortfilter/> | |||||
* <param name="comparator" value="org.apache.tools.ant.filters.EvenFirstCmp"/> | |||||
* </sortfilter/> | |||||
* </filterchain> | |||||
* </copy> | |||||
* </pre> | |||||
* | |||||
* <p> | |||||
* Sort all files <code>*.txt</code> from <i>src</i> location using as | |||||
* sorting criterium <code>EvenFirstCmp</code> class, that sorts the file | |||||
* lines putting even lines first then odd lines for example. The modified files | |||||
* are copied into <i>build</i> location. The <code>EventFirstCmp</code>, | |||||
* has to an instanciable class via <code>Class.newInstance()</code>, | |||||
* therefore in case of inner class has to be <em>static</em>. It also has to | |||||
* implement <code>java.util.Comparator</code> interface, for example: | |||||
* </p> | |||||
* | |||||
* <pre> | |||||
* package org.apache.tools.ant.filters; | |||||
* ...(omitted) | |||||
* public final class EvenFirstCmp implements <b>Comparator</b> { | |||||
* public int compare(Object o1, Object o2) { | |||||
* ...(omitted) | |||||
* } | |||||
* } | |||||
* </pre> | |||||
* | |||||
* <p> If parameter <code>comparator</code> is present, then | |||||
* <code>reverse</code> parameter will not taken into account. </p> | |||||
* | |||||
* @since Ant 1.8.0 | |||||
*/ | |||||
public final class SortFilter extends BaseParamFilterReader | |||||
implements ChainableReader { | |||||
/** Parameter name for reverse order. */ | |||||
private static final String REVERSE_KEY = "reverse"; | |||||
/** | |||||
* Parameter name for specifying the comparator criteria via class that | |||||
* implement <code>java.util.Comparator</code> interface. | |||||
*/ | |||||
private static final String COMPARATOR_KEY = "comparator"; | |||||
/** | |||||
* Instance of comparator class to be used for sorting. | |||||
*/ | |||||
private Comparator comparator = null; | |||||
/** | |||||
* Controls if the sorting process will be in ascendant/descendant order. If | |||||
* If has value <code>true</code>, then the line of the file will be | |||||
* sorted on descendant order. Default value: <code>false</code>. It will | |||||
* be considered only if <code>comparator</code> is <code>null</code>. | |||||
*/ | |||||
private boolean reverse; | |||||
/** | |||||
* Stores the lines to be sorted. | |||||
*/ | |||||
private List lines; | |||||
/** | |||||
* Remaining line to be read from this filter, or <code>null</code> if the | |||||
* next call to <code>read()</code> should read the original stream to | |||||
* find the next matching line. | |||||
*/ | |||||
private String line = null; | |||||
private Iterator iterator = null; | |||||
/** | |||||
* Constructor for "dummy" instances. | |||||
* | |||||
* @see BaseFilterReader#BaseFilterReader() | |||||
*/ | |||||
public SortFilter() { | |||||
super(); | |||||
} | |||||
/** | |||||
* Creates a new filtered reader. | |||||
* | |||||
* @param in | |||||
* A Reader object providing the underlying stream. Must not be | |||||
* <code>null</code>. | |||||
*/ | |||||
public SortFilter(final Reader in) { | |||||
super(in); | |||||
} | |||||
/** | |||||
* Returns the next character in the filtered stream. If the desired number | |||||
* of lines have already been read, the resulting stream is effectively at | |||||
* an end. Otherwise, the next character from the underlying stream is read | |||||
* and returned. | |||||
* | |||||
* @return the next character in the resulting stream, or -1 if the end of | |||||
* the resulting stream has been reached | |||||
* | |||||
* @exception IOException | |||||
* if the underlying stream throws an IOException during | |||||
* reading | |||||
*/ | |||||
public int read() throws IOException { | |||||
if (!getInitialized()) { | |||||
initialize(); | |||||
setInitialized(true); | |||||
} | |||||
int ch = -1; | |||||
if (line != null) { | |||||
/* | |||||
* We are on the state: "reading the current line", lines are | |||||
* already sorted | |||||
*/ | |||||
ch = line.charAt(0); | |||||
if (line.length() == 1) { | |||||
line = null; | |||||
} else { | |||||
line = line.substring(1); | |||||
} | |||||
} else { | |||||
if (lines == null) { | |||||
// We read all lines and sort them | |||||
lines = new ArrayList(); | |||||
for (line = readLine(); line != null; line = readLine()) { | |||||
lines.add(line); | |||||
} | |||||
sort(); | |||||
iterator = lines.iterator(); | |||||
} | |||||
if (iterator.hasNext()) { | |||||
line = (String) iterator.next(); | |||||
} else { | |||||
line = null; | |||||
lines = null; | |||||
iterator = null; | |||||
} | |||||
if (line != null) { | |||||
return read(); | |||||
} | |||||
} | |||||
return ch; | |||||
} | |||||
/** | |||||
* Creates a new SortReader using the passed in Reader for instantiation. | |||||
* | |||||
* @param rdr | |||||
* A Reader object providing the underlying stream. Must not be | |||||
* <code>null</code>. | |||||
* | |||||
* @return a new filter based on this configuration, but filtering the | |||||
* specified reader | |||||
*/ | |||||
public Reader chain(final Reader rdr) { | |||||
SortFilter newFilter = new SortFilter(rdr); | |||||
newFilter.setReverse(isReverse()); | |||||
newFilter.setComparator(getComparator()); | |||||
newFilter.setInitialized(true); | |||||
return newFilter; | |||||
} | |||||
/** | |||||
* Returns <code>true</code> if the sorting process will be in reverse | |||||
* order, otherwise the sorting process will be in ascendant order. | |||||
* | |||||
* @return <code>true</code> if the sorting process will be in reverse | |||||
* order, otherwise the sorting process will be in ascendant order. | |||||
*/ | |||||
public boolean isReverse() { | |||||
return reverse; | |||||
} | |||||
/** | |||||
* Sets the sorting process will be in ascendant (<code>reverse=false</code>) | |||||
* or to descendant (<code>reverse=true</code>). | |||||
* | |||||
* @param reverse | |||||
* Boolean representing reverse ordering process. | |||||
*/ | |||||
public void setReverse(boolean reverse) { | |||||
this.reverse = reverse; | |||||
} | |||||
/** | |||||
* Returns the comparator to be used for sorting. | |||||
* | |||||
* @return the comparator | |||||
*/ | |||||
public Comparator getComparator() { | |||||
return comparator; | |||||
} | |||||
/** | |||||
* Set the comparator to be used as sorting criterium. | |||||
* | |||||
* @param comparator | |||||
* the comparator to set | |||||
*/ | |||||
public void setComparator(Comparator comparator) { | |||||
this.comparator = comparator; | |||||
} | |||||
/** | |||||
* Set the comparator to be used as sorting criterium as nested element. | |||||
* | |||||
* @param comparator | |||||
* the comparator to set | |||||
*/ | |||||
public void add(Comparator comparator) { | |||||
if (this.comparator != null && comparator != null) { | |||||
throw new BuildException("can't have more than one comparator"); | |||||
} | |||||
setComparator(comparator); | |||||
} | |||||
/** | |||||
* Scans the parameters list | |||||
*/ | |||||
private void initialize() throws IOException { | |||||
// get parameters | |||||
Parameter[] params = getParameters(); | |||||
if (params != null) { | |||||
for (int i = 0; i < params.length; i++) { | |||||
final String paramName = params[i].getName(); | |||||
if (REVERSE_KEY.equals(paramName)) { | |||||
setReverse(Boolean.valueOf(params[i].getValue()) | |||||
.booleanValue()); | |||||
continue; | |||||
} | |||||
if (COMPARATOR_KEY.equals(paramName)) { | |||||
try { | |||||
String className = (String) params[i].getValue(); | |||||
setComparator((Comparator) (Class.forName(className) | |||||
.newInstance())); | |||||
continue; | |||||
} catch (InstantiationException e) { | |||||
throw new BuildException(e); | |||||
} catch (IllegalAccessException e) { | |||||
/* | |||||
* Probably a inner non-static class, this this case is | |||||
* not considered | |||||
*/ | |||||
throw new BuildException(e); | |||||
} catch (ClassNotFoundException e) { | |||||
throw new BuildException(e); | |||||
} catch (ClassCastException e) { | |||||
throw new BuildException("Value of comparator attribute" | |||||
+ " should implement" | |||||
+ " java.util.Comparator" | |||||
+ " interface"); | |||||
} catch (Exception e) { | |||||
throw new BuildException(e); | |||||
} | |||||
} | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Sorts the read lines (<code>lines</code>)acording to the sorting | |||||
* criteria defined by the user. | |||||
* | |||||
*/ | |||||
private void sort() { | |||||
if (comparator == null) { | |||||
if (reverse) { | |||||
Collections.sort(lines, new Comparator() { | |||||
public int compare(Object o1, Object o2) { | |||||
String s1 = (String) o1; | |||||
String s2 = (String) o2; | |||||
return (-s1.compareTo(s2)); | |||||
} | |||||
}); | |||||
} else { | |||||
Collections.sort(lines); | |||||
} | |||||
} else { | |||||
Collections.sort(lines, comparator); | |||||
} | |||||
} | |||||
} |
@@ -0,0 +1,10 @@ | |||||
Line 2 | |||||
Line 4 | |||||
Line 6 | |||||
Line 8 | |||||
Line 10 | |||||
Line 1 | |||||
Line 3 | |||||
Line 5 | |||||
Line 7 | |||||
Line 9 |
@@ -0,0 +1,10 @@ | |||||
Line 1 | |||||
Line 2 | |||||
Line 3 | |||||
Line 4 | |||||
Line 5 | |||||
Line 6 | |||||
Line 7 | |||||
Line 8 | |||||
Line 9 | |||||
Line 10 |
@@ -0,0 +1,10 @@ | |||||
Line 10 | |||||
Line 9 | |||||
Line 8 | |||||
Line 7 | |||||
Line 6 | |||||
Line 5 | |||||
Line 4 | |||||
Line 3 | |||||
Line 2 | |||||
Line 1 |
@@ -0,0 +1,10 @@ | |||||
Line 10 | |||||
Line 1 | |||||
Line 9 | |||||
Line 6 | |||||
Line 3 | |||||
Line 2 | |||||
Line 4 | |||||
Line 5 | |||||
Line 7 | |||||
Line 8 |
@@ -0,0 +1,126 @@ | |||||
<?xml version="1.0"?> | |||||
<!-- | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
--> | |||||
<project default="antunit" xmlns:au="antlib:org.apache.ant.antunit"> | |||||
<import file="../antunit-base.xml" /> | |||||
<target name="setUp"> | |||||
<mkdir dir="${output}"/> | |||||
</target> | |||||
<target name="testSortFilterNoArgs" depends="setUp"> | |||||
<copy file="input/sort.sortDefault.test" | |||||
tofile="${output}/sort.sortDefault.test"> | |||||
<filterchain> | |||||
<sortfilter/> | |||||
</filterchain> | |||||
</copy> | |||||
<au:assertFilesMatch | |||||
expected="expected/sort.sortDefault.test" | |||||
actual="${output}/sort.sortDefault.test"/> | |||||
</target> | |||||
<target name="testSortFilterNoArgsLong" depends="setUp"> | |||||
<copy file="input/sort.sortDefault.test" | |||||
tofile="${output}/sort.sortDefault.test"> | |||||
<filterchain> | |||||
<filterreader classname="org.apache.tools.ant.filters.SortFilter"/> | |||||
</filterchain> | |||||
</copy> | |||||
<au:assertFilesMatch | |||||
expected="expected/sort.sortDefault.test" | |||||
actual="${output}/sort.sortDefault.test"/> | |||||
</target> | |||||
<target name="testSortFilterReverse" depends="setUp"> | |||||
<copy file="input/sort.sortDefault.test" | |||||
tofile="${output}/sort.sortReverse.test"> | |||||
<filterchain> | |||||
<sortfilter reverse="true"/> | |||||
</filterchain> | |||||
</copy> | |||||
<au:assertFilesMatch | |||||
expected="expected/sort.sortReverse.test" | |||||
actual="${output}/sort.sortReverse.test"/> | |||||
</target> | |||||
<target name="testSortFilterReverseLong" depends="setUp"> | |||||
<copy file="input/sort.sortDefault.test" | |||||
tofile="${output}/sort.sortReverse.test"> | |||||
<filterchain> | |||||
<filterreader classname="org.apache.tools.ant.filters.SortFilter"> | |||||
<param name="reverse" value="true"/> | |||||
</filterreader> | |||||
</filterchain> | |||||
</copy> | |||||
<au:assertFilesMatch | |||||
expected="expected/sort.sortReverse.test" | |||||
actual="${output}/sort.sortReverse.test"/> | |||||
</target> | |||||
<target name="-setUpEvenFirst" depends="setUp"> | |||||
<mkdir dir="${input}/src/org/apache/tools/ant/filters"/> | |||||
<echo file="${input}/src/org/apache/tools/ant/filters/EvenFirstCmp.java"><![CDATA[ | |||||
package org.apache.tools.ant.filters; | |||||
import java.util.Comparator; | |||||
public final class EvenFirstCmp implements Comparator { | |||||
public int compare(Object o1, Object o2) { | |||||
String s1 = ((String) o1).substring(5).trim(); | |||||
String s2 = ((String) o2).substring(5).trim(); | |||||
int n1 = Integer.parseInt(s1); | |||||
int n2 = Integer.parseInt(s2); | |||||
if (n1 % 2 == 0) { | |||||
if (n2 % 2 == 0) { | |||||
return n1 - n2; | |||||
} else { | |||||
return -1; | |||||
} | |||||
} else { | |||||
if (n2 % 2 == 0) { | |||||
return 1; | |||||
} else { | |||||
return n1 - n2; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
]]></echo> | |||||
<mkdir dir="${input}/build"/> | |||||
<javac srcdir="${input}/src" destdir="${input}/build"/> | |||||
<typedef classname="org.apache.tools.ant.filters.EvenFirstCmp" | |||||
name="evenfirst"> | |||||
<classpath location="${input}/build"/> | |||||
</typedef> | |||||
</target> | |||||
<target name="testSortFilterComparator" depends="-setUpEvenFirst"> | |||||
<copy file="input/sort.sortDefault.test" | |||||
tofile="${output}/sort.sortComparator.test"> | |||||
<filterchain> | |||||
<sortfilter> | |||||
<evenfirst/> | |||||
</sortfilter> | |||||
</filterchain> | |||||
</copy> | |||||
<au:assertFilesMatch | |||||
expected="expected/sort.sortComparator.test" | |||||
actual="${output}/sort.sortComparator.test"/> | |||||
</target> | |||||
</project> |