@@ -46,6 +46,11 @@ Other changes: | |||||
properties with values taken as snapshots from the | properties with values taken as snapshots from the | ||||
availableProcessors, freeMemory, maxMemory and totalMemory methods | availableProcessors, freeMemory, maxMemory and totalMemory methods | ||||
of the Java Runtime class. | of the Java Runtime class. | ||||
* linecontains filter now has a new "matchAny" attribute which when | |||||
set to "true" allows any (instead of all) of the user-specified | |||||
strings to be present in the line. | |||||
Bugzilla Report 62313 | |||||
Changes from Ant 1.10.2 TO Ant 1.10.3 | Changes from Ant 1.10.2 TO Ant 1.10.3 | ||||
===================================== | ===================================== | ||||
@@ -318,6 +318,16 @@ the source distribution).</p> | |||||
<td>Whether to select <em>non-</em>matching lines only. <em>Since Ant 1.7</em></td> | <td>Whether to select <em>non-</em>matching lines only. <em>Since Ant 1.7</em></td> | ||||
<td>No</td> | <td>No</td> | ||||
</tr> | </tr> | ||||
<tr> | |||||
<td>matchAny</td> | |||||
<td>If <em>false</em>, then all the strings are expected to be present in the line. If | |||||
<em>true</em>, then the presence of any of the strings in the line, is considered | |||||
a successful match. Defaults to <em>false</em>. | |||||
<br/> | |||||
<em>Since Ant 1.10.4</em> | |||||
</td> | |||||
<td>No</td> | |||||
</tr> | |||||
</table> | </table> | ||||
<p> | <p> | ||||
<h4>Example</h4> | <h4>Example</h4> | ||||
@@ -145,4 +145,31 @@ | |||||
<fail unless="filterchain.files.are.same">File was modified</fail> | <fail unless="filterchain.files.are.same">File was modified</fail> | ||||
</target> | </target> | ||||
<target name="testMatchAny" depends="setUp"> | |||||
<copy todir="${output}"> | |||||
<fileset dir="input"> | |||||
<include name="linecontains.test"/> | |||||
</fileset> | |||||
<filterchain> | |||||
<linecontains matchAny="true"> | |||||
<contains value="beta"/> | |||||
<contains value="alpha"/> | |||||
</linecontains> | |||||
</filterchain> | |||||
</copy> | |||||
</target> | |||||
<target name="testMatchAnyNegate" depends="setUp"> | |||||
<copy todir="${output}"> | |||||
<fileset dir="input"> | |||||
<include name="linecontains.test"/> | |||||
</fileset> | |||||
<filterchain> | |||||
<linecontains matchAny="true" negate="true"> | |||||
<contains value="beta"/> | |||||
<contains value="alpha"/> | |||||
</linecontains> | |||||
</filterchain> | |||||
</copy> | |||||
</target> | |||||
</project> | </project> |
@@ -0,0 +1,2 @@ | |||||
This is line 4 with gamma. | |||||
This is line 6 with delta. |
@@ -0,0 +1,5 @@ | |||||
This is line 1 with alpha. | |||||
This is line 2 with beta. | |||||
This is line 3 with beta. | |||||
This is line 5 with beta. | |||||
This is line 7 with beta. |
@@ -25,7 +25,7 @@ import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.types.Parameter; | import org.apache.tools.ant.types.Parameter; | ||||
/** | /** | ||||
* Filter which includes only those lines that contain all the user-specified | |||||
* Filter which includes only those lines that contain the user-specified | |||||
* strings. | * strings. | ||||
* | * | ||||
* Example: | * Example: | ||||
@@ -45,6 +45,19 @@ import org.apache.tools.ant.types.Parameter; | |||||
* This will include only those lines that contain <code>foo</code> and | * This will include only those lines that contain <code>foo</code> and | ||||
* <code>bar</code>. | * <code>bar</code>. | ||||
* | * | ||||
* Starting Ant 1.10.4, the {@code matchAny} attribute can be used to control whether any one | |||||
* of the user-specified strings is expected to be contained in the line or all | |||||
* of them are expected to be contained. | |||||
* | |||||
* For example: | |||||
* | |||||
* <pre><linecontains matchAny="true"> | |||||
* * <contains value="foo"> | |||||
* * <contains value="bar"> | |||||
* * </linecontains></pre> | |||||
* | |||||
* This will include only those lines that contain either <code>foo</code> or <code>bar</code>. | |||||
* | |||||
*/ | */ | ||||
public final class LineContains | public final class LineContains | ||||
extends BaseParamFilterReader | extends BaseParamFilterReader | ||||
@@ -67,6 +80,8 @@ public final class LineContains | |||||
private boolean negate = false; | private boolean negate = false; | ||||
private boolean matchAny = false; | |||||
/** | /** | ||||
* Constructor for "dummy" instances. | * Constructor for "dummy" instances. | ||||
* | * | ||||
@@ -116,9 +131,24 @@ public final class LineContains | |||||
for (line = readLine(); line != null; line = readLine()) { | for (line = readLine(); line != null; line = readLine()) { | ||||
boolean matches = true; | boolean matches = true; | ||||
for (int i = 0; matches && i < containsSize; i++) { | |||||
String containsStr = contains.elementAt(i); | |||||
for (int i = 0; i < containsSize; i++) { | |||||
final String containsStr = contains.elementAt(i); | |||||
matches = line.contains(containsStr); | matches = line.contains(containsStr); | ||||
if (!matches) { | |||||
if (this.matchAny) { | |||||
// this one didn't match, but we are expected to have | |||||
// any one of them match. so try next | |||||
continue; | |||||
} else { | |||||
// all were expected to match, but this one didn't. | |||||
// so no point checking the rest | |||||
break; | |||||
} | |||||
} else if (this.matchAny) { | |||||
// we were expected to match any of the contains | |||||
// and this one did. so no more checks needed | |||||
break; | |||||
} | |||||
} | } | ||||
if (matches ^ isNegated()) { | if (matches ^ isNegated()) { | ||||
break; | break; | ||||
@@ -157,6 +187,31 @@ public final class LineContains | |||||
return negate; | return negate; | ||||
} | } | ||||
/** | |||||
* | |||||
* @param matchAny True if this {@link LineContains} is considered a match, | |||||
* if {@code any} of the {@code contains} value match. False | |||||
* if {@code all} of the {@code contains} value are expected | |||||
* to match | |||||
* @since Ant 1.10.4 | |||||
* | |||||
*/ | |||||
public void setMatchAny(final boolean matchAny) { | |||||
this.matchAny = matchAny; | |||||
} | |||||
/** | |||||
* @return Returns true if this {@link LineContains} is considered a match, | |||||
* if {@code any} of the {@code contains} value match. False | |||||
* if {@code all} of the {@code contains} value are expected | |||||
* to match | |||||
* | |||||
* @since Ant 1.10.4 | |||||
*/ | |||||
public boolean isMatchAny() { | |||||
return this.matchAny; | |||||
} | |||||
/** | /** | ||||
* Sets the vector of words which must be contained within a line read | * Sets the vector of words which must be contained within a line read | ||||
* from the original stream in order for it to match this filter. | * from the original stream in order for it to match this filter. | ||||
@@ -195,6 +250,7 @@ public final class LineContains | |||||
LineContains newFilter = new LineContains(rdr); | LineContains newFilter = new LineContains(rdr); | ||||
newFilter.setContains(getContains()); | newFilter.setContains(getContains()); | ||||
newFilter.setNegate(isNegated()); | newFilter.setNegate(isNegated()); | ||||
newFilter.setMatchAny(isMatchAny()); | |||||
return newFilter; | return newFilter; | ||||
} | } | ||||
@@ -53,4 +53,30 @@ public class LineContainsTest { | |||||
buildRule.executeTarget("testNegateLineContains"); | buildRule.executeTarget("testNegateLineContains"); | ||||
} | } | ||||
/** | |||||
* Tests that the {@code matchAny} attribute of {@link LineContains} works as expected | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
@Test | |||||
public void testLineContainsMatchAny() throws IOException { | |||||
buildRule.executeTarget("testMatchAny"); | |||||
File expected = buildRule.getProject().resolveFile("expected/linecontains-matchany.test"); | |||||
File result = new File(buildRule.getProject().getProperty("output"), "linecontains.test"); | |||||
assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result)); | |||||
} | |||||
/** | |||||
* Tests that the {@code matchAny} attribute when used with the {@code negate} attribute | |||||
* of {@link LineContains} works as expected | |||||
* | |||||
* @throws IOException | |||||
*/ | |||||
@Test | |||||
public void testLineContainsMatchAnyNegate() throws IOException { | |||||
buildRule.executeTarget("testMatchAnyNegate"); | |||||
File expected = buildRule.getProject().resolveFile("expected/linecontains-matchany-negate.test"); | |||||
File result = new File(buildRule.getProject().getProperty("output"), "linecontains.test"); | |||||
assertEquals(FileUtilities.getFileContents(expected), FileUtilities.getFileContents(result)); | |||||
} | |||||
} | } |