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"); | ||||
| } | } | ||||