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 | |||
to include only resources meeting specified criteria</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="#intersect">intersect</a> - set intersection | |||
of nested resource collections</li> | |||
@@ -514,6 +516,19 @@ platforms. | |||
<p>Sorts another nested resource collection according to the resources' | |||
natural order, or by one or more nested resource comparators:</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">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> | |||
<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.content">content</a> - sort resources by content</li> | |||
<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> | |||
<h4><a name="rcmp.name">name</a></h4> | |||
@@ -570,10 +585,38 @@ natural order, or by one or more nested resource comparators:</p> | |||
</table> | |||
<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> | |||
<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> | |||
<blockquote> | |||
<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> | |||
<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> | |||
<hr> | |||
@@ -599,4 +657,4 @@ natural order, or by one or more nested resource comparators:</p> | |||
Reserved.</p> | |||
</body> | |||
</html> | |||
</html> |
@@ -445,6 +445,50 @@ depends="testfileurl,testfileurlref,testhttpurl1,testhttpurl2,testjarurl,testres | |||
<target name="single" | |||
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> |
@@ -54,6 +54,7 @@ difference=org.apache.tools.ant.types.resources.Difference | |||
intersect=org.apache.tools.ant.types.resources.Intersect | |||
sort=org.apache.tools.ant.types.resources.Sort | |||
resources=org.apache.tools.ant.types.resources.Resources | |||
first=org.apache.tools.ant.types.resources.First | |||
#Resources (single-element ResourceCollections): | |||
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"); | |||
} | |||
public void testfirst1() { | |||
executeTarget("testfirst1"); | |||
} | |||
public void testfirst2() { | |||
executeTarget("testfirst2"); | |||
} | |||
public void testhttpurl1() { | |||
executeTarget("testhttpurl1"); | |||
} | |||