BaseResourceCollectionWrapper. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278491 13f79535-47bb-0310-9956-ffa450edef68master
@@ -222,6 +222,8 @@ Ant's "legacy" datatypes have been modified to behave as Resource Collections: | |||||
<li><a href="#restrict">restrict</a> - restrict a resource collection | <li><a href="#restrict">restrict</a> - restrict a resource collection | ||||
to include only resources meeting specified criteria</li> | to include only resources meeting specified criteria</li> | ||||
<li><a href="#sort">sort</a> - sorted resource collection</li> | <li><a href="#sort">sort</a> - sorted resource collection</li> | ||||
<li><a href="#first">first</a> - first <i>n</i> resources from a | |||||
nested collection</li> | |||||
<li><a href="#union">union</a> - set union of nested resource collections</li> | <li><a href="#union">union</a> - set union of nested resource collections</li> | ||||
<li><a href="#intersect">intersect</a> - set intersection | <li><a href="#intersect">intersect</a> - set intersection | ||||
of nested resource collections</li> | of nested resource collections</li> | ||||
@@ -514,6 +516,19 @@ platforms. | |||||
<p>Sorts another nested resource collection according to the resources' | <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 resource comparators:</p> | ||||
<blockquote> | <blockquote> | ||||
<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">cache</td> | |||||
<td valign="top">Whether to cache results; disabling | |||||
may seriously impact performance</td> | |||||
<td valign="top" align="center">No, default <i>true</i></td> | |||||
</tr> | |||||
</table> | |||||
<h4>Parameters specified as nested elements</h4> | <h4>Parameters specified as nested elements</h4> | ||||
<p>A single resource collection is required.</p> | <p>A single resource collection is required.</p> | ||||
<p>The sort can be controlled and customized by specifying one or more | <p>The sort can be controlled and customized by specifying one or more | ||||
@@ -532,7 +547,7 @@ natural order, or by one or more nested resource comparators:</p> | |||||
<li><a href="#rcmp.size">size</a> - sort resources by size</li> | <li><a href="#rcmp.size">size</a> - sort resources by size</li> | ||||
<li><a href="#rcmp.content">content</a> - sort resources by content</li> | <li><a href="#rcmp.content">content</a> - sort resources by content</li> | ||||
<li><a href="#rcmp.reverse">reverse</a> - reverse the natural sort order, | <li><a href="#rcmp.reverse">reverse</a> - reverse the natural sort order, | ||||
or a single nested resource comparator</li> | |||||
or that of a single nested resource comparator</li> | |||||
</ul> | </ul> | ||||
<h4><a name="rcmp.name">name</a></h4> | <h4><a name="rcmp.name">name</a></h4> | ||||
@@ -570,10 +585,38 @@ natural order, or by one or more nested resource comparators:</p> | |||||
</table> | </table> | ||||
<h4><a name="rcmp.reverse">reverse</a></h4> | <h4><a name="rcmp.reverse">reverse</a></h4> | ||||
<p>Reverse the natural sort order, or a single nested comparator.</p> | |||||
<p>Reverse the natural sort order, or that of a single nested comparator.</p> | |||||
</blockquote> | </blockquote> | ||||
<h4><a name="first">first</a></h4> | |||||
<p>Includes the first <i>count</i> resources from a nested resource collection. | |||||
This can be used in conjunction with the <a href="#sort">sort</a> collection, | |||||
for example, to select the first few oldest, largest, etc. resources from a | |||||
larger collection.</p> | |||||
<blockquote> | |||||
<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">count</td> | |||||
<td valign="top">The number of resources to include</td> | |||||
<td valign="top" align="center">No, default 1</td> | |||||
</tr> | |||||
<tr> | |||||
<td valign="top">cache</td> | |||||
<td valign="top">Whether to cache results; disabling | |||||
may seriously impact performance</td> | |||||
<td valign="top" align="center">No, default <i>true</i></td> | |||||
</tr> | |||||
</table> | |||||
<h4>Parameters specified as nested elements</h4> | |||||
<p>A single resource collection is required.</p> | |||||
</blockquote> | |||||
<h4><a name="setlogic">Set operations</a></h4> | <h4><a name="setlogic">Set operations</a></h4> | ||||
<blockquote> | <blockquote> | ||||
<p>The following resource collections implement set operations:</p> | <p>The following resource collections implement set operations:</p> | ||||
@@ -592,6 +635,21 @@ natural order, or by one or more nested resource comparators:</p> | |||||
<h4><a name="difference">difference</a></h4> | <h4><a name="difference">difference</a></h4> | ||||
<p>Difference of nested resource collections.</p> | <p>Difference of nested resource collections.</p> | ||||
<p>The following attributes apply to all set-operation resource collections: | |||||
</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">cache</td> | |||||
<td valign="top">Whether to cache results; disabling | |||||
may seriously impact performance</td> | |||||
<td valign="top" align="center">No, default <i>true</i></td> | |||||
</tr> | |||||
</table> | |||||
</blockquote> | </blockquote> | ||||
<hr> | <hr> | ||||
@@ -599,4 +657,4 @@ natural order, or by one or more nested resource comparators:</p> | |||||
Reserved.</p> | Reserved.</p> | ||||
</body> | </body> | ||||
</html> | |||||
</html> |
@@ -445,6 +445,50 @@ depends="testfileurl,testfileurlref,testhttpurl1,testhttpurl2,testjarurl,testres | |||||
<target name="single" | <target name="single" | ||||
depends="testresource,url,testfile,string,testzipentry,testproperty" /> | depends="testresource,url,testfile,string,testzipentry,testproperty" /> | ||||
<target name="all" depends="legacy,files,resources,setlogic,single" /> | |||||
<target name="testfirst0"> | |||||
<fail> | |||||
<condition> | |||||
<not> | |||||
<resourcecount count="0"> | |||||
<first count="0"> | |||||
<filelist dir="${dir}" files="1,2,3,4,5" /> | |||||
</first> | |||||
</resourcecount> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
</target> | |||||
<target name="testfirst1"> | |||||
<fail> | |||||
<condition> | |||||
<not> | |||||
<resourcecount count="1"> | |||||
<first> | |||||
<filelist dir="${dir}" files="1,2,3,4,5" /> | |||||
</first> | |||||
</resourcecount> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
</target> | |||||
<target name="testfirst2"> | |||||
<fail> | |||||
<condition> | |||||
<not> | |||||
<resourcecount count="2"> | |||||
<first count="2"> | |||||
<filelist dir="${dir}" files="1,2,3,4,5" /> | |||||
</first> | |||||
</resourcecount> | |||||
</not> | |||||
</condition> | |||||
</fail> | |||||
</target> | |||||
<target name="first" depends="testfirst0,testfirst1,testfirst2" /> | |||||
<target name="all" depends="legacy,files,resources,setlogic,single,first" /> | |||||
</project> | </project> |
@@ -54,6 +54,7 @@ difference=org.apache.tools.ant.types.resources.Difference | |||||
intersect=org.apache.tools.ant.types.resources.Intersect | intersect=org.apache.tools.ant.types.resources.Intersect | ||||
sort=org.apache.tools.ant.types.resources.Sort | sort=org.apache.tools.ant.types.resources.Sort | ||||
resources=org.apache.tools.ant.types.resources.Resources | resources=org.apache.tools.ant.types.resources.Resources | ||||
first=org.apache.tools.ant.types.resources.First | |||||
#Resources (single-element ResourceCollections): | #Resources (single-element ResourceCollections): | ||||
resource=org.apache.tools.ant.types.Resource | resource=org.apache.tools.ant.types.Resource | ||||
@@ -0,0 +1,203 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed 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; | |||||
import java.io.File; | |||||
import java.util.List; | |||||
import java.util.Stack; | |||||
import java.util.Iterator; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import org.apache.tools.ant.Project; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.DataType; | |||||
import org.apache.tools.ant.types.ResourceCollection; | |||||
/** | |||||
* Base class for a ResourceCollection that wraps a single nested | |||||
* ResourceCollection. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public abstract class BaseResourceCollectionWrapper | |||||
extends DataType implements ResourceCollection, Cloneable { | |||||
private static final String ONE_NESTED_MESSAGE | |||||
= " expects exactly one nested resource collection."; | |||||
private ResourceCollection rc; | |||||
private Collection coll = null; | |||||
private boolean cache = true; | |||||
/** | |||||
* Set whether to cache collections. | |||||
* @param b boolean cache flag. | |||||
*/ | |||||
public synchronized void setCache(boolean b) { | |||||
cache = b; | |||||
} | |||||
/** | |||||
* Learn whether to cache collections. Default is <code>true</code>. | |||||
* @return boolean cache flag. | |||||
*/ | |||||
public synchronized boolean isCache() { | |||||
return cache; | |||||
} | |||||
/** | |||||
* Add a ResourceCollection to the container. | |||||
* @param c the ResourceCollection to add. | |||||
* @throws BuildException on error. | |||||
*/ | |||||
public synchronized void add(ResourceCollection c) throws BuildException { | |||||
if (isReference()) { | |||||
throw noChildrenAllowed(); | |||||
} | |||||
if (c == null) { | |||||
return; | |||||
} | |||||
if (rc != null) { | |||||
throwOneNested(); | |||||
} | |||||
rc = c; | |||||
setChecked(false); | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return an Iterator of Resources. | |||||
*/ | |||||
public synchronized final Iterator iterator() { | |||||
if (isReference()) { | |||||
return ((BaseResourceCollectionWrapper) getCheckedRef()).iterator(); | |||||
} | |||||
dieOnCircularReference(); | |||||
return cacheCollection().iterator(); | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return number of elements as int. | |||||
*/ | |||||
public synchronized int size() { | |||||
if (isReference()) { | |||||
return ((BaseResourceCollectionWrapper) getCheckedRef()).size(); | |||||
} | |||||
dieOnCircularReference(); | |||||
return cacheCollection().size(); | |||||
} | |||||
/** | |||||
* Fulfill the ResourceCollection contract. | |||||
* @return whether this is a filesystem-only resource collection. | |||||
*/ | |||||
public synchronized boolean isFilesystemOnly() { | |||||
if (isReference()) { | |||||
return ((BaseResourceCollectionContainer) getCheckedRef()).isFilesystemOnly(); | |||||
} | |||||
dieOnCircularReference(); | |||||
if (rc == null || rc.isFilesystemOnly()) { | |||||
return true; | |||||
} | |||||
/* now check each Resource in case the child only | |||||
lets through files from any children IT may have: */ | |||||
for (Iterator i = cacheCollection().iterator(); i.hasNext();) { | |||||
if (!(i.next() instanceof FileResource)) { | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
} | |||||
/** | |||||
* Overrides the version of DataType to recurse on all DataType | |||||
* child elements that may have been added. | |||||
* @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 (rc instanceof DataType) { | |||||
stk.push(rc); | |||||
invokeCircularReferenceCheck((DataType) rc, stk, p); | |||||
stk.pop(); | |||||
} | |||||
setChecked(true); | |||||
} | |||||
} | |||||
/** | |||||
* Get the nested ResourceCollection. | |||||
* @return a ResourceCollection. | |||||
* @throws BuildException if no nested ResourceCollection has been provided. | |||||
*/ | |||||
protected synchronized final ResourceCollection getResourceCollection() { | |||||
dieOnCircularReference(); | |||||
if (rc == null) { | |||||
throwOneNested(); | |||||
} | |||||
return rc; | |||||
} | |||||
/** | |||||
* Template method for subclasses to return a Collection of Resources. | |||||
* @return Collection. | |||||
*/ | |||||
protected abstract Collection getCollection(); | |||||
/** | |||||
* Format this BaseResourceCollectionWrapper as a String. | |||||
* @return a descriptive <code>String</code>. | |||||
*/ | |||||
public synchronized String toString() { | |||||
if (isReference()) { | |||||
return getCheckedRef().toString(); | |||||
} | |||||
if (cacheCollection().size() == 0) { | |||||
return ""; | |||||
} | |||||
StringBuffer sb = new StringBuffer(); | |||||
for (Iterator i = coll.iterator(); i.hasNext();) { | |||||
if (sb.length() > 0) { | |||||
sb.append(File.pathSeparatorChar); | |||||
} | |||||
sb.append(i.next()); | |||||
} | |||||
return sb.toString(); | |||||
} | |||||
private synchronized Collection cacheCollection() { | |||||
if (coll == null || !isCache()) { | |||||
coll = getCollection(); | |||||
} | |||||
return coll; | |||||
} | |||||
private void throwOneNested() throws BuildException { | |||||
throw new BuildException(super.toString() + ONE_NESTED_MESSAGE); | |||||
} | |||||
} |
@@ -0,0 +1,72 @@ | |||||
/* | |||||
* Copyright 2005 The Apache Software Foundation | |||||
* | |||||
* Licensed 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; | |||||
import java.util.List; | |||||
import java.util.Iterator; | |||||
import java.util.ArrayList; | |||||
import java.util.Collection; | |||||
import java.util.Collections; | |||||
import org.apache.tools.ant.BuildException; | |||||
import org.apache.tools.ant.types.ResourceCollection; | |||||
/** | |||||
* ResourceCollection that contains the first <code>count</code> elements of | |||||
* another ResourceCollection. | |||||
* @since Ant 1.7 | |||||
*/ | |||||
public class First extends BaseResourceCollectionWrapper { | |||||
private static final String BAD_COUNT | |||||
= "count of first resources should be set to an int >= 0"; | |||||
private int count = 1; | |||||
/** | |||||
* Set the number of resources to be included. | |||||
* @param i the count as <code>int</count>. | |||||
*/ | |||||
public synchronized void setCount(int i) { | |||||
count = i; | |||||
} | |||||
/** | |||||
* Get the number of resources to be included. Default is 1. | |||||
* @return the count as <code>int</count>. | |||||
*/ | |||||
public synchronized int getCount() { | |||||
return count; | |||||
} | |||||
/** | |||||
* Take the first <code>count</code> elements. | |||||
* @return a Collection of Resources. | |||||
*/ | |||||
protected Collection getCollection() { | |||||
int ct = getCount(); | |||||
if (ct < 0) { | |||||
throw new BuildException(BAD_COUNT); | |||||
} | |||||
Iterator iter = getResourceCollection().iterator(); | |||||
ArrayList al = new ArrayList(ct); | |||||
for (int i = 0; i < ct && iter.hasNext(); i++) { | |||||
al.add(iter.next()); | |||||
} | |||||
return al; | |||||
} | |||||
} |
@@ -73,6 +73,14 @@ public class ResourceCollectionsTest extends BuildFileTest { | |||||
executeTarget("testfileurlref"); | executeTarget("testfileurlref"); | ||||
} | } | ||||
public void testfirst1() { | |||||
executeTarget("testfirst1"); | |||||
} | |||||
public void testfirst2() { | |||||
executeTarget("testfirst2"); | |||||
} | |||||
public void testhttpurl1() { | public void testhttpurl1() { | ||||
executeTarget("testhttpurl1"); | executeTarget("testhttpurl1"); | ||||
} | } | ||||