| @@ -46,6 +46,11 @@ Other changes: | |||
| properties with values taken as snapshots from the | |||
| availableProcessors, freeMemory, maxMemory and totalMemory methods | |||
| 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 | |||
| ===================================== | |||
| @@ -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>No</td> | |||
| </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> | |||
| <p> | |||
| <h4>Example</h4> | |||
| @@ -145,4 +145,31 @@ | |||
| <fail unless="filterchain.files.are.same">File was modified</fail> | |||
| </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> | |||
| @@ -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; | |||
| /** | |||
| * Filter which includes only those lines that contain all the user-specified | |||
| * Filter which includes only those lines that contain the user-specified | |||
| * strings. | |||
| * | |||
| * Example: | |||
| @@ -45,6 +45,19 @@ import org.apache.tools.ant.types.Parameter; | |||
| * This will include only those lines that contain <code>foo</code> and | |||
| * <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 | |||
| extends BaseParamFilterReader | |||
| @@ -67,6 +80,8 @@ public final class LineContains | |||
| private boolean negate = false; | |||
| private boolean matchAny = false; | |||
| /** | |||
| * Constructor for "dummy" instances. | |||
| * | |||
| @@ -116,9 +131,24 @@ public final class LineContains | |||
| for (line = readLine(); line != null; line = readLine()) { | |||
| 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); | |||
| 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()) { | |||
| break; | |||
| @@ -157,6 +187,31 @@ public final class LineContains | |||
| 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 | |||
| * 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); | |||
| newFilter.setContains(getContains()); | |||
| newFilter.setNegate(isNegated()); | |||
| newFilter.setMatchAny(isMatchAny()); | |||
| return newFilter; | |||
| } | |||
| @@ -53,4 +53,30 @@ public class LineContainsTest { | |||
| 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)); | |||
| } | |||
| } | |||