Browse Source

Added <compare> resource selector to select resources based on the

results of their comparison to other resources. Inspired by userlist thread
http://marc.theaimsgroup.com/?t=115998761500004&r=1&w=2 .
Still lacks an example other than testcases. :(


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@454842 13f79535-47bb-0310-9956-ffa450edef68
master
Matthew Jason Benson 18 years ago
parent
commit
66838f3c29
6 changed files with 396 additions and 6 deletions
  1. +3
    -0
      WHATSNEW
  2. +32
    -2
      docs/manual/CoreTypes/resources.html
  3. +139
    -0
      src/main/org/apache/tools/ant/types/Quantifier.java
  4. +153
    -0
      src/main/org/apache/tools/ant/types/resources/selectors/Compare.java
  5. +2
    -0
      src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml
  6. +67
    -4
      src/tests/antunit/types/resources/selectors/test.xml

+ 3
- 0
WHATSNEW View File

@@ -66,6 +66,9 @@ Other changes:
* Added <tokens> resource collection for convenient creation of string
resources from other resources' content. Inspired by Bugzilla 40504.

* Added <compare> resource selector to select resources based on the
results of their comparison to other resources.

Changes from Ant 1.7.0Beta1 to Ant 1.7.0Beta2
=============================================



+ 32
- 2
docs/manual/CoreTypes/resources.html View File

@@ -463,6 +463,8 @@ platforms.
containing a particular text string.</li>
<li><a href="selectors.html#regexpselect">containsregexp</a> - select
resources whose contents match a particular regular expression.</li>
<li><a href="#rsel.compare">compare</a> - select resources
based on comparison to other resources.</li>
</ul>

<h4><a name="rsel.name">name</a></h4>
@@ -621,12 +623,40 @@ platforms.
</tr>
</table>

<h4><a name="rsel.compare">compare</a></h4>
<p>Selects a resource based on its comparison to one or more "control"
resources using nested <a href="#rcmp">resource comparators</a>.</p>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">when</td>
<td valign="top">Comparison ("equal"/"eq", "greater"/"gt", "less"/"lt",
"le" (less or equal), "ge" (greater or equal), "ne" (not equal).</td>
<td valign="top">No, default "equal"</td>
</tr>
<tr>
<td valign="top">against</td>
<td valign="top">Quantifier ("all"/"each"/"every", "any"/"some",
(exactly) "one", "most"/"majority", "none".</td>
<td valign="top">No, default "all"</td>
</tr>
</table>
<h4>Parameters specified as nested elements</h4>
<p>The resources against which comparisons will be made must be specified
using the nested &lt;control&gt; element, which denotes a
<a href="#resources">resources</a> collection.</p>

</blockquote>

<h4><a name="sort">sort</a></h4>

<p>Sorts another nested resource collection according to the resources'
natural order, or by one or more nested resource comparators:</p>
natural order, or by one or more nested <a href="#rcmp">resource
comparators</a>:</p>
<blockquote>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
@@ -650,7 +680,7 @@ natural order, or by one or more nested resource comparators:</p>
are available in the internal <a href="antlib.html">antlib</a>
<code>org.apache.tools.ant.types.resources.comparators</code>:
</p>
<h4><a name="rcmp">Resource Comparators:</a></h4>
<ul>
<li><a href="#rcmp.name">name</a> - sort resources by name</li>
<li><a href="#rcmp.exists">exists</a> - sort resources by existence</li>


+ 139
- 0
src/main/org/apache/tools/ant/types/Quantifier.java View File

@@ -0,0 +1,139 @@
/*
* 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.types;

import org.apache.tools.ant.BuildException;

/**
* EnumeratedAttribute for quantifier comparisons. Evaluates a
* <code>boolean[]</code> or raw <code>true</code> and <code>false</code>
* counts. Accepts the following values:<ul>
* <li>"all"</li> - none <code>false</code>
* <li>"each"</li> - none <code>false</code>
* <li>"every"</li> - none <code>false</code>
* <li>"any"</li> - at least one <code>true</code>
* <li>"some"</li> - at least one <code>true</code>
* <li>"one"</li> - exactly one <code>true</code>
* <li>"majority"</li> - more <code>true</code> than <code>false</code>
* <li>"most"</li> - more <code>true</code> than <code>false</code>
* <li>"none"</li> - none <code>true</code>
* </ul>
* @since Ant 1.7
*/
public class Quantifier extends EnumeratedAttribute {
private static final String[] VALUES
= new String[] {"all", "each", "every", "any", "some", "one",
"majority", "most", "none"};

public static final Quantifier ALL = new Quantifier("all");
public static final Quantifier ANY = new Quantifier("any");
public static final Quantifier ONE = new Quantifier("one");
public static final Quantifier MAJORITY = new Quantifier("majority");
public static final Quantifier NONE = new Quantifier("none");

private static abstract class Predicate {
abstract boolean eval(int t, int f);
}

private static final Predicate ALL_PRED = new Predicate() {
boolean eval(int t, int f) { return f == 0; }
};

private static final Predicate ANY_PRED = new Predicate() {
boolean eval(int t, int f) { return t > 0 ; }
};

private static final Predicate ONE_PRED = new Predicate() {
boolean eval(int t, int f) { return t == 1; }
};

private static final Predicate MAJORITY_PRED = new Predicate() {
boolean eval(int t, int f) { return t > f; }
};

private static final Predicate NONE_PRED = new Predicate() {
boolean eval(int t, int f) { return t == 0; }
};

private static final Predicate[] PREDS = new Predicate[VALUES.length];

static {
PREDS[0] = ALL_PRED;
PREDS[1] = ALL_PRED;
PREDS[2] = ALL_PRED;
PREDS[3] = ANY_PRED;
PREDS[4] = ANY_PRED;
PREDS[5] = ONE_PRED;
PREDS[6] = MAJORITY_PRED;
PREDS[7] = MAJORITY_PRED;
PREDS[8] = NONE_PRED;
}

/**
* Default constructor.
*/
public Quantifier() {
}

/**
* Construct a new Quantifier with the specified value.
* @param value the EnumeratedAttribute value.
*/
public Quantifier(String value) {
setValue(value);
}

/**
* Return the possible values.
* @return String[] of EnumeratedAttribute values.
*/
public String[] getValues() {
return VALUES;
}

/**
* Evaluate a <code>boolean<code> array.
* @param b the <code>boolean[]</code> to evaluate.
* @return true if the argument fell within the parameters of this Quantifier.
*/
public boolean evaluate(boolean[] b) {
int t = 0;
for (int i = 0; i < b.length; i++) {
if (b[i]) {
t++;
}
}
return evaluate(t, b.length - t);
}

/**
* Evaluate integer <code>true</code> vs. <code>false</code> counts.
* @param t the number of <code>true</code> values.
* @param f the number of <code>false</code> values.
* @return true if the arguments fell within the parameters of this Quantifier.
*/
public boolean evaluate(int t, int f) {
int index = getIndex();
if (index == -1) {
throw new BuildException("Quantifier value not set.");
}
return PREDS[index].eval(t, f);
}

}


+ 153
- 0
src/main/org/apache/tools/ant/types/resources/selectors/Compare.java View File

@@ -0,0 +1,153 @@
/*
* 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.types.resources.selectors;

import java.util.Stack;
import java.util.Vector;
import java.util.TreeMap;
import java.util.Iterator;
import java.util.Collection;
import java.util.Comparator;
import java.util.Collections;
import java.util.AbstractCollection;
import java.util.NoSuchElementException;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.types.Comparison;
import org.apache.tools.ant.types.DataType;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.Quantifier;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.types.resources.comparators.ResourceComparator;
import org.apache.tools.ant.types.resources.comparators.DelegatedResourceComparator;

/**
* ResourceSelector that compares against "control" Resource(s)
* using ResourceComparators.
* @since Ant 1.7
*/
public class Compare extends DataType implements ResourceSelector {

private static final String ONE_CONTROL_MESSAGE
= " the <control> element should be specified exactly once.";

private DelegatedResourceComparator comp = new DelegatedResourceComparator();
private Quantifier against = Quantifier.ALL;

private Comparison when = Comparison.EQUAL;

private Union control;

/**
* Add a ResourceComparator to this Compare selector.
* If multiple ResourceComparators are added, they will be processed in LIFO order.
* @param c the ResourceComparator to add.
*/
public synchronized void add(ResourceComparator c) {
if (isReference()) {
throw noChildrenAllowed();
}
comp.add(c);
}

/**
* Set the quantifier to be used. Default "all".
* @param against the Quantifier EnumeratedAttribute to use.
*/
public synchronized void setAgainst(Quantifier against) {
if (isReference()) {
throw tooManyAttributes();
}
this.against = against;
}

/**
* Set the comparison to be used. Default "equal".
* @param when the Comparison EnumeratedAttribute to use.
*/
public synchronized void setWhen(Comparison when) {
if (isReference()) {
throw tooManyAttributes();
}
this.when = when;
}

/**
* Create the nested control element. These are the
* resources to compare against.
* @return ResourceCollection.
*/
public synchronized ResourceCollection createControl() {
if (isReference()) {
throw noChildrenAllowed();
}
if (control != null) {
throw oneControl();
}
control = new Union();
return control;
}

//implement ResourceSelector; inherit doc
public synchronized boolean isSelected(Resource r) {
if (isReference()) {
return ((ResourceSelector) getCheckedRef()).isSelected(r);
}
if (control == null) {
throw oneControl();
}
int t = 0, f = 0;
for (Iterator it = control.iterator(); it.hasNext();) {
if (when.evaluate(comp.compare(r, (Resource) it.next()))) {
t++;
} else {
f++;
}
}
return against.evaluate(t, f);
}

/**
* Overrides the version from DataType
* to recurse on nested ResourceComparators.
* @param stk the stack of data types to use (recursively).
* @param p the project to use to dereference the references.
* @throws BuildException on error.
*/
protected synchronized void dieOnCircularReference(Stack stk, Project p)
throws BuildException {
if (isChecked()) {
return;
}
if (isReference()) {
super.dieOnCircularReference(stk, p);
} else {
if (control != null) {
DataType.invokeCircularReferenceCheck(control, stk, p);
}
DataType.invokeCircularReferenceCheck(comp, stk, p);
setChecked(true);
}
}

private BuildException oneControl() {
return new BuildException(super.toString() + ONE_CONTROL_MESSAGE);
}
}

+ 2
- 0
src/resources/org/apache/tools/ant/types/resources/selectors/antlib.xml View File

@@ -1,6 +1,8 @@
<antlib>
<typedef name="and"
classname="org.apache.tools.ant.types.resources.selectors.And" />
<typedef name="compare"
classname="org.apache.tools.ant.types.resources.selectors.Compare" />
<typedef name="contains"
classname="org.apache.tools.ant.types.selectors.ContainsSelector" />
<typedef name="containsregexp"


+ 67
- 4
src/tests/antunit/types/resources/selectors/test.xml View File

@@ -1,5 +1,6 @@
<project default="all" xmlns:au="antlib:org.apache.ant.antunit"
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors">
xmlns:rsel="antlib:org.apache.tools.ant.types.resources.selectors"
xmlns:rcmp="antlib:org.apache.tools.ant.types.resources.comparators">

<target name="testname1">
<au:assertTrue>
@@ -99,7 +100,7 @@
</au:assertTrue>
</target>

<target name="testinstanceoftype"
<target name="instanceoftype"
depends="testinstanceoftype1,testinstanceoftype2,testinstanceoftype3" />

<target name="testinstanceofclass">
@@ -115,7 +116,7 @@
</au:assertTrue>
</target>

<target name="instanceof" depends="testinstanceoftype,testinstanceofclass" />
<target name="instanceof" depends="instanceoftype,testinstanceofclass" />

<target name="testtype">
<au:assertTrue>
@@ -358,6 +359,68 @@
</au:assertTrue>
</target>

<target name="testcompare">
<au:assertTrue>
<and>
<!-- basic test, natural ordering -->
<resourcecount count="3">
<restrict>
<rsel:compare when="greater" against="each">
<control><string value="b" /></control>
</rsel:compare>
<resources>
<string value="a" />
<string value="b" />
<string value="c" />
<string value="d" />
<string value="e" />
</resources>
</restrict>
</resourcecount>
<!-- one comparator, default when/against -->
<resourcecount count="5">
<restrict>
<rsel:compare>
<control><string value="." /></control>
<rcmp:size />
</rsel:compare>
<resources>
<string value="a" />
<string value="b" />
<string value="c" />
<string value="d" />
<string value="e" />
</resources>
</restrict>
</resourcecount>
<!-- multiple controls, comparators -->
<resourcecount count="3">
<restrict>
<rsel:compare when="greater" against="each">
<control>
<string value="a" />
<string value="b" />
<string value="bb" />
<string value="c" />
<string value="ccc" />
</control>
<rcmp:name />
<rcmp:size />
</rsel:compare>
<resources>
<string value="a" />
<string value="bbbb" />
<string value="ccc" />
<string value="cccc" />
<string value="d" />
<string value="e" />
</resources>
</restrict>
</resourcecount>
</and>
</au:assertTrue>
</target>

<target name="majority"
depends="testmajority1,testmajority2,testmajority3,testmajority4" />

@@ -365,7 +428,7 @@
depends="testand,testor,testnone,testnot,majority" />

<target name="all"
depends="name,testexists,instanceof,testtype,testdate,testsize,testcontains,testcontainsregexp,logical" />
depends="name,testexists,instanceof,testtype,testdate,testsize,testcontains,testcontainsregexp,logical,testcompare" />

<!--
The tests for oata.types.selectors.ModifiedSelectorTest as


Loading…
Cancel
Save